|
What do people mean when they say a method doesn't change
the observable state of an object?
It's very useful to separate methods into those that change state
and those that don't. Non-state changing methods (which I call
queries), can be used in any context without worrying about how they
sequence with other methods. The key here is not so much that they don't change any state, but
they don't change observable state. The observable state of an
object is what can be detected from its query methods - let me
illustrate with a couple of quick examples. The simplest example is that of a cache. Imagine a range class
like this.
# ruby
class MyRange
attr_reader :start, :finish
def initialize start, finish
@start, @finish = start, finish
@lengthCache = nil
end
def length
@lengthCache = (@finish - @start) unless @lengthCache
return @lengthCache
end
end
Here we have a lengthCache variable that is filled on the first
access using LazyInitialization. Putting a value in the
lengthCache clearly changes the real state of the object. It doesn't
change the observable state because you can't tell that the object's
state has changed from the outside. By can't tell from the outside I mean that the result of calling
any method on MyRange from another object will be the same whether or not the
lengthCache value is filled. Typically you'd get this affect by
ensuring that any method on MyRange uses the length method to get
the range rather than using the field directly. Cache's are an
obvious case of state whose changes should never be observable. It's
also true that any lazy initialization shouldn't change observable state.
|