I do know that the best practice these days is to model immutable classes in Java. An ex: below
// It makes sense to model this in an immmutable fashion
class 2DPoint {
private int x;
private int y;
2DPoint(int x, int Y) {
this.x = x;
this.y = y;
}
public Int getXCoordinate() {
return this.x;
}
public Int getYCoordinate() {
return this.y;
}
}
But how do you model a real world mutable object like a Car as a mutable class. If you modelled it as an immutable class like ImmutableCar given below, you'd have different object instances referencing the same real world car at different ticks of time. This feels like a violation of the inspirations for object oriented design where you let real world objects almost guide how you think about software
The other reason to model something as a mutable class is if your mutable constructor parameters that you store as private variables are too expensive to defensively copy
public Car {
private int fuel;
.....
public int addFuel(int amount) {
this.fuel += amount;
return this.fuel;
}
}
public ImmutableCar {
private final int fuel;
public ImmutableCar() {
this.fuel = 0;
}
public ImmutableCar(int fuel) {
this.fuel = fuel;
}
...
public ImmutableCar addFuel(int amount) {
return new ImmutableCar(fuel + amount);
}
}
However the dangers of mutable classes are:
- Concurrency is a lot harder if you have multiple threads trying to update the same object. You'll need to think of mutual exclusion and introduce locks
- If you have multiple classes holding a reference to a mutable object, you lose local reasoning within a class. Each class holding a reference loses its ability to control the state lifecycle of the mutable object and a programmer can't reason locally about invariants. They'd need to be aware of the other classes holding references, and this breaks modularity and introduces coupling in a sense.
So given these tradeoffs, is it always preferable to model classes in an immutable fashion, even if they represent real world mutable objects?