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

Immutable Java

Immutable Java

Slides from my talk at Java Day Riga 2013
http://www.javaday.lv/

Tero Parviainen

November 26, 2013
Tweet

More Decks by Tero Parviainen

Other Decks in Technology

Transcript

  1. Shared mutable state should be minimized and controlled. ! Not

    just for concurrency, but for understandability.
  2. Wicket “In Wicket, all server side state is automatically managed.

    You will never directly use an HttpSession object or similar wrapper to store state. Instead, state is associated with components. Each server- side page component holds a nested hierarchy of stateful components.” http://wicket.apache.org/meet/introduction.html
  3. Hibernate “Hibernate is a full object/relational mapping solution that not

    only shields the developer from the details of the underlying database management system, but also offers state management of objects. […] In other words, Hibernate application developers should always think about the state of their objects, and not necessarily about the execution of SQL statements.” http://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch11.html
  4. Cache Trolling Ehcache Web services “Customer 4 pls" Customer 4

    customer.setName(“trololo”) “Customer 4 pls" Customer 4
  5. “An immutable object is an object whose state cannot be

    modified after it is created.” Wikipedia
  6. public class Customer {! ! public final long id;! public

    final String name;! public final Address address;! ! public Customer(long id, String name, Address a) {! this.id = id;! this.name = name;! this.address = a;! }! ! }
  7. public class Address {! ! public final String street, zip,

    city;! ! public Address(String s, String z, String c) {! this.street = s;! this.zip = z;! this.city = c;! }! ! }
  8. Primitives byte b = 8;! short s = 255;! int

    i = 42;! long l = 1234567890;! float f = 3.14f;! double dbl = 3.14;! boolean bool = true;! char chr = 'c';
  9. Primitive Wrappers Byte bWrap = new Byte(b);! Short sWrap =

    new Short(s);! Integer iWrap = new Integer(i);! Long lWrap = new Long(l);! Float fWrap = new Float(f);! Double dblWrap = new Double(dbl);! Boolean boolWrap = new Boolean(bool);! Character chrWrap = new Character(chr);
  10. Strings String str = "abc ";! ! String trimmed =

    str.trim();! String firstChar = str.substring(0, 1);! String replaced = str.replace(' ', '.');! String another = str + "def";
  11. Dates Date aDate = new Date();! aDate.setMonth(4);! ! Calendar aCalendar

    = Calendar.getInstance();! aCalendar.set(Calendar.MONTH, 4);!
  12. int[] arr = {1, 2, 3};! arr[1] = 4;! !

    List<Integer> lst = new ArrayList<>();! lst.add(5);! lst.remove(0);! ! Set<Integer> set = new HashSet<>(lst);! set.add(4);! ! Map<Integer, String> map = new HashMap<>();! map.put(1, "one");
  13. Immutability By Convention public void timesTwo(List<Integer> ns) {! for (int

    i=0 ; i < ns.size() ; i++) {! ns.set(i, ns.get(i) * 2);! }! }
  14. Immutability By Convention public List<Integer> timesTwo(List<Integer> ns) {! List<Integer> result

    = new ArrayList<>();! for (Integer n : ns) {! result.add(n * 2);! }! return result;! }!
  15. JDK 8 Streams public List<Integer> timesTwo(List<Integer> ns) {! return ns!

    .stream()! .map(n -> n * 2)! .collect(Collectors.toList());! }!
  16. “There’s no such thing as a convention of immutability, as

    anyone who has tried to enforce one can attest. ! If a data structure offers only an immutable API, that is what’s most important. ! If it offers a mixed API, it’s simply not immutable.” Rich Hickey
  17. Unmodifiable Collections List<Integer> lst = new ArrayList<>();! lst.add(1);! lst.add(2);! !

    List<Integer> unmodable = ! Collections.unmodifiableList(lst);! unmodable.add(3);! Exception in thread "main" java.lang.UnsupportedOperationException! ! at java.util.Collections $UnmodifiableCollection.add(Collections.java:1115)
  18. List<Integer> lst = new ArrayList<>();! lst.add(1);! lst.add(2);! ! List<Integer> unmodable

    = ! Collections.unmodifiableList(lst);! ! lst.add(3);! Unmodifiable Collections
  19. Immutable Collections Google Guava ImmutableList<Integer> lst = ImmutableList.of(1, 2);! !

    ImmutableList<Integer> other =! new ImmutableList.Builder<Integer>()! .addAll(lst)! .add(3)! .build();!
  20. “A persistent data structure is a data structure that always

    preserves the previous version of itself when it is modified. Such data structures are effectively immutable, as their operations do not (visibly) update the structure in-place, but instead always yield a new updated structure.” Wikipedia
  21. Clojure Collections PersistentVector v = PersistentVector.create(1, 2);! PersistentVector other =

    v.cons(3);! ! ! ! IPersistentMap map = PersistentHashMap.EMPTY;! map = map.assoc(1, "one");! map = map.assoc(2, "two");! ! String two = (String)map.valAt(2);!
  22. Clojure Collections PersistentVector<Integer> v =! Persistents.vector(1, 2);! PersistentVector<Integer> other =

    v.plus(3);! ! PersistentMap<Integer, String> map =! Persistents.hashMap(1, "one", 2, "two");! ! String two = map.get(2);! Wrapped, clj-ds
  23. pcollections PCollection<Integer> c =! TreePVector.singleton(1).plus(2);! PCollection<Integer> other = c.plus(3);! !

    ! PMap<Integer, String> map =! HashTreePMap.singleton(1, "one").plus(2, "two");! ! String two = map.get(2);!
  24. Immutable Objects public class Address {! ! public final String

    street, zip, city;! ! public Address(String s, String z, String c) {! this.street = s;! this.zip = z;! this.city = c;! }! ! }
  25. Producing New Versions public Address withStreet(String street) {! return new

    Address(street, this.zip, this.city);! }! “with” methods
  26. “An object defined primarily by its identity is called an

    ENTITY. An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT. ! Immutability is a great simplifier in an implementation. […] It is also consistent with the meaning of a value. If the value of an attribute changes, you use a different VALUE OBJECT, rather than modifying the existing one.” Eric Evans
  27. “When designing a system, it’s important to distinguish between values

    […] and objects. ! Values are immutable instances that model fixed quantities. They have no individual identity, so two value instances are effectively the same if they have the same state. Objects, on the other hand, use mutable state to model their behavior over time.” Steve Freeman & Nat Pryce
  28. State in Clojure An identity can be in different states

    at different times, but the state itself doesn't change. That is, an identity is not a state, an identity has a state. Exactly one state at any point in time. And that state is a true value, i.e. it never changes. If an identity appears to change, it is because it becomes associated with different state values over time. This is the Clojure model. http://clojure.org/state
  29. Separation of Concerns Customer ! name address ! Address !

    street zip city Value Value immutable immutable CustomerRef ! id customer ! Identity mutable
  30. “I think that the ideal program contains a whole lot

    of immutable code in functional style and then small pieces of mutable code, doing imperative things, but having them be very localised and separate from the data and separate from the core behaviour of the system.” Gary Bernhardt, Destroy All Software
  31. Summary • Shared mutable state hurts understandability. • Most state

    isn’t necessary. • The rest should be isolated and controlled. • We have the building blocks we need. • DDD and GOOS advise when & how. • The Clojure state model goes one further. • Frameworks may get in the way. Quarantine them.