Slide 1

Slide 1 text

Immutable Java @teropa

Slide 2

Slide 2 text

Shared mutable state should be minimized and controlled. ! Not just for concurrency, but for understandability.

Slide 3

Slide 3 text

2001 2006 2007 2008 Java Ruby JS Clojure Personal Timeline

Slide 4

Slide 4 text

A Project, ~2008 Spring Wicket Hibernate Ehcache DB Web services

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Time-Sensitivity Wicket session Hibernate session Transaction Web requests

Slide 10

Slide 10 text

Cache Trolling Ehcache Web services “Customer 4 pls" Customer 4 customer.setName(“trololo”) “Customer 4 pls" Customer 4

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Eliminating State

Slide 13

Slide 13 text

Spring «Stateless Web Framework» «Stateless DB access» Ehcache DB Web services

Slide 14

Slide 14 text

Immutability

Slide 15

Slide 15 text

“An immutable object is an object whose state cannot be modified after it is created.” Wikipedia

Slide 16

Slide 16 text

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;! }! ! }

Slide 17

Slide 17 text

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;! }! ! }

Slide 18

Slide 18 text

Building Blocks

Slide 19

Slide 19 text

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';

Slide 20

Slide 20 text

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);

Slide 21

Slide 21 text

Strings String str = "abc ";! ! String trimmed = str.trim();! String firstChar = str.substring(0, 1);! String replaced = str.replace(' ', '.');! String another = str + "def";

Slide 22

Slide 22 text

Dates Date aDate = new Date();! aDate.setMonth(4);! ! Calendar aCalendar = Calendar.getInstance();! aCalendar.set(Calendar.MONTH, 4);!

Slide 23

Slide 23 text

JSR 310 LocalDate aDate = LocalDate.now();! LocalDate lastApril = aDate.withMonth(4);!

Slide 24

Slide 24 text

Collections

Slide 25

Slide 25 text

int[] arr = {1, 2, 3};! arr[1] = 4;! ! List lst = new ArrayList<>();! lst.add(5);! lst.remove(0);! ! Set set = new HashSet<>(lst);! set.add(4);! ! Map map = new HashMap<>();! map.put(1, "one");

Slide 26

Slide 26 text

Immutability By Convention public void timesTwo(List ns) {! for (int i=0 ; i < ns.size() ; i++) {! ns.set(i, ns.get(i) * 2);! }! }

Slide 27

Slide 27 text

Immutability By Convention public List timesTwo(List ns) {! List result = new ArrayList<>();! for (Integer n : ns) {! result.add(n * 2);! }! return result;! }!

Slide 28

Slide 28 text

JDK 8 Streams public List timesTwo(List ns) {! return ns! .stream()! .map(n -> n * 2)! .collect(Collectors.toList());! }!

Slide 29

Slide 29 text

“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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Unmodifiable Collections

Slide 32

Slide 32 text

List lst = new ArrayList<>();! lst.add(1);! lst.add(2);! ! List unmodable = ! Collections.unmodifiableList(lst);! ! lst.add(3);! Unmodifiable Collections

Slide 33

Slide 33 text

Immutable Collections Google Guava ImmutableList lst = ImmutableList.of(1, 2);! ! ImmutableList other =! new ImmutableList.Builder()! .addAll(lst)! .add(3)! .build();!

Slide 34

Slide 34 text

Persistent Collections

Slide 35

Slide 35 text

“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

Slide 36

Slide 36 text

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);!

Slide 37

Slide 37 text

Clojure Collections PersistentVector v =! Persistents.vector(1, 2);! PersistentVector other = v.plus(3);! ! PersistentMap map =! Persistents.hashMap(1, "one", 2, "two");! ! String two = map.get(2);! Wrapped, clj-ds

Slide 38

Slide 38 text

pcollections PCollection c =! TreePVector.singleton(1).plus(2);! PCollection other = c.plus(3);! ! ! PMap map =! HashTreePMap.singleton(1, "one").plus(2, "two");! ! String two = map.get(2);!

Slide 39

Slide 39 text

Object Models

Slide 40

Slide 40 text

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;! }! ! }

Slide 41

Slide 41 text

Producing New Versions public Address withStreet(String street) {! return new Address(street, this.zip, this.city);! }! “with” methods

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

“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

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

“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

Slide 46

Slide 46 text

Customer ! id name address Address ! street zip city Entity Value mutable immutable

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Separation of Concerns Customer ! name address ! Address ! street zip city Value Value immutable immutable CustomerRef ! id customer ! Identity mutable

Slide 49

Slide 49 text

Systems

Slide 50

Slide 50 text

Spring Wicket Hibernate Ehcache DB Web services Web UI

Slide 51

Slide 51 text

Ports and Adapters Hibernate DB Ehcache Web services W icket Web UI Pure Domain

Slide 52

Slide 52 text

Hibernate DB Ehcache Web services W icket Web UI Functional Core Imperative Shell

Slide 53

Slide 53 text

“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

Slide 54

Slide 54 text

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.

Slide 55

Slide 55 text

Thanks! @teropa is.gd/vertxbook