What appears at first to be a trivial observation turns out to be a subtly important one: a large number software defects arise from the (incorrect) modification of state. It follows from this that if there is less opportunity for code to change state, there will be fewer defects that arise from state change.

What appears at first to be a trivial observation turns out to be a subtly important one: a large number software defects arise from the (incorrect) modification of state. It follows from this that if there is less opportunity for code to change state, there will be fewer defects that arise from state change.

-

Perhaps the most obvious example of restricting mutability is its most complete realization: immutability. A moratorium on state change is an idea carried to its logical conclusion in functional programming, but even its modest application in the context of other programming models has a simplifying effect. If an object is immutable it can be shared freely across different parts of a program without concern for aliasing or synchronization problems. An object that does not change state is inherently thread-safe -- there is no need to synchronize state change if there is no state change. An immutable object does not need locking or any other palliative workaround to achieve safety. Immutability is particularly suitable for value objects in languages that favor predominantly reference-based semantics. For example, Java's <code>String</code> class represents objects that are essentially immutable -- if you want another string value, you use another string object.

+

Perhaps the most obvious example of restricting mutability is its most complete realization: immutability. A moratorium on state change is an idea carried to its logical conclusion in pure functional programming languages such as Haskell, but even its modest application in the context of other programming models has a simplifying effect. If an object is immutable it can be shared freely across different parts of a program without concern for aliasing or synchronization problems. An object that does not change state is inherently thread-safe &mdash; there is no need to synchronize state change if there is no state change. An immutable object does not need locking or any other palliative workaround to achieve safety.

-

A related approach to immutability is through qualification, such as the <code>const</code> feature found in C++ and D. Object usage can be constrained with respect to the mutability declared for accessing the object. The set of operations on a qualified object is restricted to those that are similarly qualified. In C++ and D <code>const</code> qualification typically expresses the notion of read-only, which is clearly a restriction on mutability, but D also offers <code>immutable</code> for declaring full immutability.

+

Depending on the language and the idiom, immutability can be expressed in the definition of a type or through the declaration of a variable. For example, Java's <code>String</code> class represents objects that are essentially immutable &mdash; if you want another string value, you use another string object. Immutability is particularly suitable for value objects in languages that favor predominantly reference-based semantics. The <code>const</code> qualifier found in C and C++ and the <code>immutable</code> qualifier in D constrain mutability through declaration. In C++ <code>const</code> qualification restricts mutability in terms of access rights, typically expressing the notion of read-only access and not necessarily full immutability.

-

Perhaps a little counterintuitively, copying offers a complementary technique for restricting mutability. In languages offering a transparent syntax for passing by copy, such as C#'s <code>struct</code> objects and C++, copying value objects can greatly improve encapsulation and reduce opportunities for unnecessary and unintended state change. Passing or returning a copy of a value object ensures that the caller and callee cannot interfere with one another's view a value. But note that to be effective for values, copying requires a transparent passing syntax: if the programmer has to make special efforts to remember to make the copy, such as explicitly call a clone method, they are also being the opportunity to forget to do it. It becomes a complication that is easy to overlook rather than a simplification.

+

Perhaps a little counterintuitively, copying offers a complementary technique for restricting mutability. In languages offering a transparent syntax for passing by copy, such as C#'s <code>struct</code> objects and C++, copying value objects can greatly improve encapsulation and reduce opportunities for unnecessary and unintended state change. Passing or returning a copy of a value object ensures that the caller and callee cannot interfere with one another's view a value. But note that to be effective for values, copying requires a transparent passing syntax: if the programmer has to make special efforts to remember to make the copy, such as explicitly call a clone method, they are also being given the opportunity to forget to do it. It becomes a complication that is easy to overlook rather than a simplification.

-

Another way to restrict the mutability of state is to reduce the scope in which it is accessed. Declare a variable as close to its point of use as possible. For local variables, declare as late as possible, only when a variable can be sensibly initialised. For variables with longer lifetimes, improving locality reduces the scope for change. Global data has the broadest scope possible. Keep in mind that public class-wide variables are simply globals with scope etiquette.

+

Another way to restrict the mutability of state is to reduce the scope in which it is accessed. Declare a variable as close to its point of use as possible. For local variables, declare as late as possible, only when a variable can be sensibly initialised. For variables with longer lifetimes, improving locality reduces the scope for change. Global data has the broadest scope possible. Keep in mind that public class-wide variables &mdash; <code>static</code> variables in many languages &mdash; are simply globals with scope etiquette.

Of course, this is not some kind of silver bullet with which to shoot down all defects, but restricting the mutability of state offers a guideline that can help to reduce the incidence of defects through improved encapsulation and code simplification.

Of course, this is not some kind of silver bullet with which to shoot down all defects, but restricting the mutability of state offers a guideline that can help to reduce the incidence of defects through improved encapsulation and code simplification.

Current revision

What appears at first to be a trivial observation turns out to be a subtly important one: a large number software defects arise from the (incorrect) modification of state. It follows from this that if there is less opportunity for code to change state, there will be fewer defects that arise from state change.

Perhaps the most obvious example of restricting mutability is its most complete realization: immutability. A moratorium on state change is an idea carried to its logical conclusion in pure functional programming languages such as Haskell, but even its modest application in the context of other programming models has a simplifying effect. If an object is immutable it can be shared freely across different parts of a program without concern for aliasing or synchronization problems. An object that does not change state is inherently thread-safe — there is no need to synchronize state change if there is no state change. An immutable object does not need locking or any other palliative workaround to achieve safety.

Depending on the language and the idiom, immutability can be expressed in the definition of a type or through the declaration of a variable. For example, Java's String class represents objects that are essentially immutable — if you want another string value, you use another string object. Immutability is particularly suitable for value objects in languages that favor predominantly reference-based semantics. The const qualifier found in C and C++ and the immutable qualifier in D constrain mutability through declaration. In C++ const qualification restricts mutability in terms of access rights, typically expressing the notion of read-only access and not necessarily full immutability.

Perhaps a little counterintuitively, copying offers a complementary technique for restricting mutability. In languages offering a transparent syntax for passing by copy, such as C#'s struct objects and C++, copying value objects can greatly improve encapsulation and reduce opportunities for unnecessary and unintended state change. Passing or returning a copy of a value object ensures that the caller and callee cannot interfere with one another's view a value. But note that to be effective for values, copying requires a transparent passing syntax: if the programmer has to make special efforts to remember to make the copy, such as explicitly call a clone method, they are also being given the opportunity to forget to do it. It becomes a complication that is easy to overlook rather than a simplification.

Another way to restrict the mutability of state is to reduce the scope in which it is accessed. Declare a variable as close to its point of use as possible. For local variables, declare as late as possible, only when a variable can be sensibly initialised. For variables with longer lifetimes, improving locality reduces the scope for change. Global data has the broadest scope possible. Keep in mind that public class-wide variables — static variables in many languages — are simply globals with scope etiquette.

Of course, this is not some kind of silver bullet with which to shoot down all defects, but restricting the mutability of state offers a guideline that can help to reduce the incidence of defects through improved encapsulation and code simplification.