The topic of Mutability has been abscent from programming textbooks

Big Mistake!

If you don't control the mutability in your code, you expose yourself to really bad things!

What was the last sentence said before Skynet took over humanity?

"I would make this
class mutable, what
could possibly go wrong?"

We know what happened next...

If NPE has caused
losses of billion of dollars, surely mutability has caused losses around
that magnitude!

Is not that people is
not aware of it!

Item 15: Minimize mutability

First edition was
written in 2001!

So let's make 2016 the
year in which mutability gains the same importance as encapsulation

Let's begin with
a warmup

What's a reference?

It's a variable which
allows the indirect

manipulation of objects

You can really think of
it as a variable that holds
the memory address
of an object

What's the state
of an Object?

The values of its attributes

What's an argument?

It's the value of a parameter
used to call a method

public class Main {
  static void times2(int n) {
    n *= 2;
  }
  public static void main(String... args) {
    int n = 1;
    times2(n);
    System.out.println(n);
  }
}

What does it print?

It prints "1"

Why?

  • Java has "pass-by-value"
  • It means that a copy of the arguments
    is made when executing a method.
  • The "n" inside times2() is a different
    variable from the "n" in main(), but have
    the same value at the time the method is called.
  • The modification inside times2() doesn't affects the argument.
public class Main {
  int n = 1;
  static void times2(Main obj) {
    obj.n *= 2;
  }
  public static void main(String... args) {
    Main obj = new Main();
    times2(obj);
    System.out.println(obj.n);
  }
}

What does it print?

It prints "2"

Why?

  • Parameter of times2() is now a reference
  • When creating obj, we create an object and get a reference to it
  • When calling times2() a copy of the argument is made: now we have 2 reference to the same object
  • "obj.n" modifies the state of the object which is accesible from 2 references!
  • After the method executes, we are left with one reference to the object, which
    was modified inside times2()

No! Java doesn't
have pass-by-reference
for Objects!

It only has pass-by-value, but since objects can only be used with references
it is similar to
pass-by-reference
in other languages

public class Main {
  int n = 1;
  static void times2(Main obj) {
    obj = new Main();
    obj.n *= 2;
  }
  public static void main(String... args) {
    Main obj = new Main();
    times2(obj);
    System.out.println(obj.n);
  }
}

What does it print?

It prints "1"

Why?

  • As soon as times2() is in the stack of execution,
    we have 2 reference to the same object
  • In the first line of code, we put the reference 
    in the method to refer to a new object. Now
    we have 2 reference pointing to different objects.
  • Changes in the state of the object inside the
    method are not related to the object outside of it.

Why do we
have references?

Mainly because it makes it cheap to copy arguments when calling methods!

How much memory
does a reference use?

Depends on the OS, typically
32-bits or 64-bits

How much memory
does an object use?

It varies from JVM to JVM but beside the size of the attributes there is usually a cost in memory associated to overhead and padding, usually 12 bytes

Since objects can contain objects, the total size of an object can be big

It would use a lot
of memory and take
a lot of time to
copy objects when
calling methods

References has other niceties like Polymorphism but memory usage was surely the first reason to have them

Going back to mutability...

When you use a reference as argument you don't know if the method will change its state!

You can go from this...

...to this

And it may take a while
until you notice

You have to be specially careful in multi-threaded environments where you depend on data sharing

Why is immutability
 desireable?

They are easy
to reason about

When you see a reference there is only one possible state for it, the one with which was constructed

You know exactly what's
the state of the arguments 
after calling a method

So how do we make
immutable objects?

Class Design revisited

We want to model
a triangle, not in the Analytic Geometry sense but the "classical" sense:
3 sides and 3 angles

Triangle

  • We need to be able to construct a
    triangle knowing its 3 sides
  • We need to know if two triangles are
    equal and have a String representation
public class Triangle {
   private Sides[] sides = new Sides[3];
   public Triangle() {
   }
   public Side getA() { return sides[0]; }
   public Side getB() { return sides[1]; }
   public Side getC() { return sides[2]; }
   public void setA(Side a) { this.a = sides[0]; }
   public void setB(Side b) { this.b = sides[1]; }
   public void setC(Side c) { this.c = sides[2]; }
   public boolean equals(Object obj) {
      if (obj == null) { return false; }
      if (obj == this) { return true; }
      if (!(obj instanceof Triangle)) { return false; }
      return Arrays.equals(sides, ((Triangle) obj).sides));
   }
}

That class has a lot of implementation that is not needed!

YAGNI

You Aren't Gonna Need It

YAGNI

  • Don't implement functionality
    until needed
  • You may waste time on something
    that doesn't add value to your client 
  • You may create a problem where
    it wasn't one

Just as is good practice to
make attributes as less visible
as possible, is also to create classes as immutable as possible

Where does
the idea of
setters-for-everything
come?!

Java Beans

What's a Java Bean

  • A class with an empty constructor
  • With getters and setters for each
    property that they have

Why do we need
Java Beans?

It's a protocol so that FW's can create objects from sources like a file or DB

So when we write

@Entity
@Table(name = "foos")
public class Foo implements java.io.Serializable {
  private String code;
  // remember this is unnecessary if there is no other constructor
  public Foo(){}  
  @Column(name = "CODE")
  public String getCode() {
    return this.code;
  }
  public void setSCode(String Code) {
    this.code = code;
  }  
}

How easy is for a FW to create Foo's objects

  • With the name of the class they can
    get an instance with reflection
  • They can call an empty constructor,
    no need to worry about the order of parameters
  • For a property xyz, they can set it values calling,
    again by reflection, a method called "set" + xyz
  • For a property xyz, they can expose it calling by reflection, a method called "get" + xyz 

When Java was getting traction, this protocol was really important so that tools such as JSF and Hibernate could blossom!

But a Java Bean is only useful when
a FW needs it, so
for everything else we can have immutable classes

Beware of classes with
only empty constructors, they seem innocent but lead to mutability!

Only use Java Beans when a FW
demands it!

Recipe to immutability

1. Make all your attributes final

2. Don't provide mutators e.g. setters

3. If you use
as a parameter  a mutable class, don't use a simple assignment, copy
its value

public class Foo {
   private final Date date;
   public Foo(Date date) {
      this.date = date; // DON'T
   }
   // more code
}
public class Foo {
  private final Date date;
  public Foo(Date date) {
    this.date = new Date(date.getTime()); // DO
  }
  // more code
}
public class Foo {
  private final LocalDateTime date;
  public Foo(LocalDateTime date) {
    this.date = date; // Is this OK?
  }
  // more code
}

Ok, since LocalDateTime
is immutable

4. Don't return references to your mutable attributes

public class Bar {
  private List<String> xyz;
  // code
  public List<String> getXyz() {
    return xyz; // DON'T
  }
}
public class Bar {
  private List<String> xyz;
  // code
  public List<String> getXyz() {
    return new ArrayList<>(xyz); // DO
  }
}
public class Bar {
  private List<String> xyz;
  // code
  public List<String> getXyz() {
    return Collection.ummodifiableList(xyz); // DO
  }
}

I like this better

Following those 4 steps create weak immutability

5. Avoid subclassing

That fifth step will give
you Strong Immutability

Avoid subclassing

  • Make class final

  • Have private constructor(s)
    and use static factories to
    create objects

String, Wrapper Classes, Classes on java.time, etc. have Strong Immutability

BigInteger, BigDecimal,
File, etc. have
Weak Immutability

Weak Immutability
is enough for most
of our projects...

...but is also true
that most of our
classes aren't meant
to be extended

Mutators

A Mutator should

return a new
object with the

updated state

public final class Fraction {
  public final int denominator;
  public final int numerator;

  public Fraction(int d, int n) {
    final int GCF = gcf(d, n);
    this.denominator = d / GCF;
    this.numerator = n / GCF;
  }

  public Fraction plus(final Fraction that) {
    final int LCM = lcm(numerator, that.numerator);
    final int denominator = LCM / this.numerator * this.denominator 
                          + LCM / that.numerator * that.denominator;
    return new Fraction(denominator, LCM);
  }
}

Returning a new
object also mean you
can chain operations

public Fraction plus(final Fraction that) {
  final int LCM = lcm(numerator, that.numerator);
  final int denominator = LCM / this.numerator * this.denominator 
	                + LCM / that.numerator * that.denominator;
  return new Fraction(denominator, LCM);
}

public Fraction opposite() {
  return new Fraction(-denominator, numerator);
}

public Fraction minus(final Fraction that) {
  return this.plus(that.opposite());
}

Wait a moment!

You are creating a lot of objects, 
that's a heavy memory footprint!

Programming is always about compromises

Mutable: fast, less memory
Immutable: safer

Computers have
come a long way,
so velocity and memory
are usually no longer
an issue

But there are
strategies that help
with memory usage

public enum Cell {
  ALIVE {
    public Cell next(int aliveNeighbors) {
      if (aliveNeighbors < 2 || aliveNeighbors > 3) {
        return DEAD;
      }
      return this;
    }
  }, 
  DEAD {
    public Cell next(int aliveNeighbors) {
      if (aliveNeighbors == 3) {
        return ALIVE;
      }
      return this;
    }
  };
  public abstract Cell next(int aliveNeighbors);
}

Is this efficient?

It is; return Singletons
or objects from a
cache or object pool

public final class Document {
   private final String title;
   private final String text;
   private final LocalDate dateOfPublish;
   // more code
   public Document withTitle(String newTitle) {
      return new Document(newTitle, this.text, this.dateOfPublish);
   }
}

Is this efficient?

Two objects can share some of
its structure to minimize memory footprint

If they share immutable objects there wouldn't
be undesirable surprises

That's the principle of the String Pool
in the JVM

LocalDateTime thePast = timePoint
                        .withDayOfMonth(10)
                        .withYear(2010);

and Java 8 Time API

Make mutators return a new object, that share as much (immutable) structure as possible

Mutability in
the inside

Mutability isn't bad per se, sharing mutability is!

You can use mutability for implementation details

public final class Board {
  private final Cell[][] board;
  private final int columns;
  private final int rows;
  private Board(Builder builder) {
    board = builder.board;
    columns = builder.columns;
    rows = builder.rows;
  }
  public static class Builder {
    private Cell[][] board;
    private int columns;
    private int rows;
    public Builder(int columns, int rows) {
      this.columns = columns;
      this.rows = rows;
      board = new Cell[columns][rows];
      for (int i = 0; i < columns; ++i) {
        Arrays.fill(board[i], Cell.DEAD);
      }
    }
    public Builder aliveCellIn(int column, int row) {
      board[column][row] = Cell.ALIVE;
      return this;
    }
    public Board build() {
      return new Board(this);
    }
  }
}

Mutability stays inside
the Builder class,
but the clients are
not exposed to it

Board board = new Board.Builder(4, 4)
        .aliveCellIn(1, 1)
        .aliveCellIn(1, 2)
        .aliveCellIn(2, 1)
        .aliveCellIn(2, 2)
        .build();
public final class Board {
  private final Cell[][] board;
  private final int columns;
  private final int rows;
  // Code
  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < columns; ++i) {
      for (int j = 0; j < rows; ++j) {
        builder.append(board[i][j]);
      }
      builder.append(String.format("%n"));
    }
    return builder.toString();
  }
}

Again, mutability
stays inside
the method

public final class Board {

  private final Cell[][] board;
  private final int columns;
  private final int rows;

  private static final int[] dx = {-1,-1,-1, 0, 0, 1, 1, 1};
  private static final int[] dy = {-1, 0, 1,-1, 1,-1, 0, 1};
  private static final int NEIGHBORS = dx.length;

  private Board(Board copy) {
    columns = copy.columns;
    rows = copy.rows;
    this.board = new Cell[columns][rows];
    for (int i = 0; i < columns; ++i) {
      this.board[i] = Arrays.copyOf(copy.board[i], rows);
    }
  }
  // Code
}
public final class Board {
  // Code
  private boolean valid(int column, int row) {
    return column >= 0 && column < columns && row >= 0 && row < rows;
  }

  private int countAliveNeighbors(int column, int row) {
    int total = 0;
    for (int i = 0; i < NEIGHBORS; ++i) {
      int nx = column + dx[i];
      int ny = row + dy[i];
      if (valid(nx, ny)) {
        total += board[nx][ny] == Cell.ALIVE ? 1 : 0;
      }
    }
    return total;
  }

  public Board next() {
    Board copy = new Board(this);
    for (int i = 0; i < columns; ++i) {
      for (int j = 0; j < rows; ++j) {
        int alive = countAliveNeighbors(i, j);
        copy.board[i][j] = board[i][j].next(alive);
      }
    }
    return copy;
  }
  // Code
}

Mutability
in the inside!

Don't fear mutability,
but don't share it!

Data Structures

Great! I'm convinced
on minimizing mutability, but how I deal
with Collections?

Collections by definition are mutable!

and Collections by definition must
be efficient!

Remember, if mutability stays in the inside
there's no harm done!

public final class Foo {
  private final List<String> list;
  public Foo(final List<String> list) {
    this.list = new ArrayList<>(Objects.requireNonNull(list));
  }
  public List<String> getList() {
    return Collections.unmodifiableList(list);
  }
}

Collections as implementation details

  • Create a new collection, all Java
    classes have copy-constructors 
  • Return an unmodifiable view of the collection;
    there is Collections.unmodifiableList(), 
    Collections.unmodifiableSet(), 
    Collections.u
    nmodifiableMap()

All functional languages have immutable data structures that use structure sharing

In Java, Guava
has them!

Java API has specialized data structures for
multi-threading appilcations

Other Tips

Use StringBuilder
and String.format()

Make all your

parameters final

Have you ever thought
of how silly it is to
mutate a parameter?

(Some) Functional languages have parameters immutable by default

public final class Document {
   private final String title;
   private final String document;
   private final String text;
   public Document(final String title, final String document, final String text) {
      this.title = Objects.requireNonNull(title);
      this.document = Objects.requireNonNull(document);
      this.text = Objects.requireNonNull(text);
   }
}

It is a little verbose!

But worth it

Use

  • setFoo(Foo foo) for typical setters
  • withFoo(Foo foo) to return a new object
    with the state but with updated value foo
  • foo(Foo foo) as getters of an inner
    Builder class to create an immutable object 

If you use immutability
and have a performance hit, first use a profiler to verify the source of the problem before changing to mutability

Let's make a vow

I vow, to the best
of my possibilities

  • to let mutability live only "in the inside"
  • to don't share mutable state
  • to explain to others why those ideas are important

Q&A

Thanks!

@gaijinco

gaijinco@gmail.com

Mutable-Types: Apocalypses

By Carlos Obregón

Mutable-Types: Apocalypses

Best practices on how to minimize mutability in your code

  • 1,843