Daniel Pitts’ Tech Blog

Posts Tagged ‘primitive’

Primitive Obsession II: (Im)mutability and Redefining Primitive

Sunday, November 4th, 2007

Last week I discussed some of the techniques for and benefits of not using simple “Primitive” values to represent your data. This article is all about taking that concept to the next level.

Let’s say that I have a value that represents an angle. I could use a double to represent the radians, or I could create a class called Angle, which internally might use a double to represent radians. If you are trying to avoid primitive obsession, you would use the latter. Now you have value objects of type Angle which can be used in meaningful ways. So, we’re done, right? I say no.

Angle is now its own form of primitive. Just as an Integer object is an abstraction of a numeric value in a specific set of reals, an Angle instance is an abstraction of a geometric/trigonometric angle. This means that it can be the building block for other more specific types. For instance, a 2 dimensional vector can be represented in “polar form” as an Angle and a Magnitude. In a physical simulation, a Magnitude is often a Distance, so we’ll assume that case for this article.

So, we can create a Vector interface (not to be confused with the java.util.Vector class). We can then create a PolarVectorImpl class which uses Angle and Distance. We can even create a CartesianVectorImpl which uses two Distance objects to represent the vector. Whats more, is these can both be used by anything that expects a Vector, with no extra work in the client code. We can easily create a rotate(Angle) method, or any other useful methods.

Another important and related concept that we haven’t touched on is mutability. If an object is mutable, that means that the apparent state of the object can change over the lifetime of the object. If an object is immutable, the apparent state of the object will appear the same throughout the lifetime of the object. This means that any invocation of one method on that object will always have the same outcome as any other on that same method. Also, any object that is returned from those methods must either be immutable themselves, or be distinct instances. Why is this important? Immutable objects have some benefits.

  • Immutable objects are inherently thread safe.
  • Immutable objects are easy to reason about.
  • Immutable objects are easier to debug.
  • Immutable objects can be passed around freely without defensive copying.

On the down side, immutability makes a pretty boring universe. If you’re object is expected to do different things depending on what has happened to it in the past, that object must be mutable. It must have state.

What does this have to do with primitive values? Its common to create immutable value objects. If we design the Angle class to be immutable, then we can safely say that one instance represents exactly one angle throughout its lifetime. All of our Angle objects are value objects. They are utility objects and reusable in many projects. On the other hand, if we’re doing a simulation of sorts, it might be useful to have a mutable angle, something that we can adjust over time. Lets call this class Heading. What’s in a Heading? An Angle, of course. Now here’s where things get interesting…

Since an Angle is a measurable thing, its easy to compare two values for equality. For Angles specifically, they are equal if their values represent the same geometric angle. Once equality is established, those objects are equal for ever. Not so with Heading. A Heading may represent the same angle at one moment in time, but at another moment they represent very different angles. For this type of object, equality only makes sense for the identity. A Heading instance is its own object, and can be queried/manipulated by many other objects/methods within the project.

The benefit of this design, is a manipulator/querier need not know who “owns” the Heading instance. A Robot might have a Heading, and a SteeringServo might manipulate that Heading. You can create the Robot and the SteeringServo objects independently of each other. The SteeringServo doesn’t even need to know its the Heading of a Robot. Once the Robot and SteeringServo both have the same Heading instance, they become connected without being coupled. This is huge goal for Object Oriented designers/programmers. The correct functioning of a SteeringServo isn’t dependent on the correct functioning of a Robot, or even of a Heading, only on itself. Similarly, a Robot’s correct functioning isn’t dependent on the correct functioning of the SteeringServo. The program as a whole may not work if there is a bug, but it easier to look at one class and ask yourself “Is there anything wrong with this code,” than it is to ask the same question about the whole project.

If you think all of this abstraction is unnecessary or unhelpful, think about all the layers beneath our Heading class. Lets have some fun and break it down into its most primitive parts.

  • Heading instance is an identity value containing an Angle and representing a direction at a point in time.
  • An Angle is an equal-comparable value containing a double and representing a direction.
  • A double is a equal-comparable and order-comparable value containing an ordered set of bits and representing a real number.
  • A bit is an equal-comparable value containing a memory cell representing true or false.
  • A memory cell is often times a capacitor that is either charged or uncharged

If you had to think about the implementation details of a bit every time you used a double, it would make the mental weight of programming so immense that no useful programs could be written. Heading can now be used very easily without adding the mental weight of how its implemented. SteeringServo can be implemented without the mental weight of what it is steering. Overall, the practice of this kind of decoupling will make your program easier for the most important source-code interpreter. You.

Avoiding Primitive Obsession

Sunday, October 28th, 2007

Particularly (but not just) programmers who have a background in C tend to think of simple data as primitive data. Measurements are one of the simplest types of data, so why not do something like this:

public class Bob {
  double distance;
  double duration;
  double weight;
  /* ... rest of code which handles calculation based on distance,
          duration, and volume, based on some predefined units for each. */
}

While there isn’t anything broken about this code, it needlessly couples the algorithms used in Bob with the units used to express distance, duration, and weight. A more robust design would give each of these there own types, which could be unit-independent. We’ll deal with just Distance. I’ve decided to implement the Distance class use meters as its underlying representation, but this fact is hidden from all clients of the class. Furthermore, I’ve tried hide that fact from as many internal methods as possible.

public final class Distance {
    private final double meters;

    private  Distance(double meters) {
        this.meters = meters;
    }

    public double getMeters() {
        return meters;
    }

    public static Distance fromMeters(double meters) {
        return new Distance(meters);
    }

    public Distance times(double scalar) {
        return fromMeters(getMeters()*scalar);
    }

    public Area times(Distance distance) {
        return Area.fromSquareMeters(getMeters() * distance.getMeters());
    }

    public Distance plus(Distance distance) {
        return fromMeters(getMeters() + distance.getMeters());
    }
}

So, what do we have here? Distance now has methods that give you more meaningful operations. A Distance multiplied by another Distance is specifically an Area, but a Distances multiplied by a scalar (simple number), is just a scaled Distance. You can’t add an arbitrary scalar to Distance on accident.

If we were using simple double distance and used the convention that distances was measured in meters, we might see code like distance+=3; // add three meters Unfortunately, if we switch to a different metric, we just broke that line. Using the non-primitive Distance, the same line would be distance = Distance.plus(Distance.fromMeters(3)); Now, no one is constrained to use meters. We could easily add fromInches, getInches, fromYards, getMicrons, etc… We could also decide change the internal representation of Distance to use BobUnits (3.14 Bob Units is one Meter ), and no client code need be touched!

Another useful example are measurements which usually have other associated values with them. For example, Angles. Angles can be measured in Degrees, Radians, and many other units. They also have associated sine, cosine, tangent. So, lets take a look at an Angle class:

public final class Angle {
    private final double radians;

    private Angle(double radians) {
        this.radians = radians;
    }

    public double cosine() {
        return Math.cos(getRadians());
    }

    public double sine() {
        return Math.sin(getRadians());
    }

    public static Angle fromCartesian(Distance x, Distance y) {
        return fromRadians(Math.atan2(y.getMeters(), x.getMeters()));
    }

    public static Angle fromRadians(double radians) {
        return new Angle(radians);
    }

    public Angle plus(Angle angle) {
        return fromRadians(getRadians() + angle.getRadians());
    }

    public double getRadians() {
        return radians;
    }
}

Again, we arbitrarily choose radians as the implementations unit, and again we don’t expose this to the client, and we don’t rely on it internally unless we have to. We have an Angle plus an Angle is an Angle. We also have a way to get an angle from a Cartesian coordinate.
What’s more, we have sine() and cosine(). That’s the big deal with Angle! Now our clients don’t need to use ugliness such as “Math.cos(angle * degreeToRadians)”. If they have an Angle, they can get the sin, cos, degrees, radians, etc… Without having to know the details of the underlying units.

Now, any of these can be turned into interfaces or abstract classes, and then you could have different implementations based on the system needs. For instance, if you’re dealing with subatomic measurements, meters doesn’t make sense for distances, and seconds doesn’t make sense for durations. You could have a MicronDistanceImpl implementation of Distance, and NanosecondDurationImpl implementation of Duration. Similarly for a cosmic simulation, you could have light-years for Distance and millennia for Duration.

Oh, almost forgot. This also gives you the ability to have nice toString() representations. I haven’t added those to the above classes, but I could imagine the toString printing “12.0 meters” and “32.6 degrees”. This will help when presenting these values to a user as well.

This kind of abstraction is what makes good design. Next time you declare something as a primitive (or a dumb primitive wrapper such as Double, or Integer), think about what type units you might assign to it. You’ll find that your classes become simpler as well, since they don’t get bogged down in the formulas needed to convert between units. It also gives you much more expressive power. Think of a Speed class which has Distance and Duration fields. Maybe even a method on Distance public Speed divide(Duration duration);