Behavior vs State

When discussing topics such as definitiveness or dependency, I'll use the word "behavior" when others might say "state". The difference might seem academic, but it has some practical ramifications that become apparent later.

The behavior of an object is what you can observe. It can be measured using the object's public interface alone. The interface is a contract that constrains an object's behavior, and that contract doesn't allow you to see anything else. This is the object-oriented concept of information hiding.

The state of an object is what it contains. You need to pierce the public interface or use a debugger to observe an object's state. A loose contract (a.k.a. a "leaky abstraction") might let some of that state show through. The object uses its own state to implement its behavior. This is the object-oriented concept of encapsulation.

So the behavior of an object is implemented in terms of state. But behavior can be described without invoking state at all. I can say that the behavior of a business object is dependent upon the behavior of a row in a database. There may be caching going on, and that cache may have state that can change. But that doesn't make it dynamic. A properly implemented cache is still dependent, because it behaves that way.

When considering the public interface of an object, behavior is all that matters. So when I want to say something about an object and its interaction with other objects, I'll limit myself to talking about behavior. I'll ignore state until it's time to code.

The behavior of numbers
Consider the number 3. I can represent this number in any of a number of ways. I can draw three vertical lines. I can hold up three fingers. I can draw the numeral 3. Or I can store the bits 00000011. These are different states that represent the object 3, depending upon its implementation.

Mathematicians have defined integers based entirely on their behavior. They say that there exists an integer called zero. They also say that if you increment or decrement any integer, you will get another integer. This is a sufficient definition, and it has nothing to do with representation.

So you can define the number 3 as the integer that you get when you increment zero, increment the result, and increment again. It doesn't matter how you store the state "3", a correct implementation will exhibit this behavior.

If we use vertical lines, you increment by drawing one more. If we use fingers, you hold up one more. If we use binary, you flip bits from left to right, stopping at the first zero-to-one transition. These are all implementation details based on state. But the behavior is always the same.

The effect of describing behavior
If I limit myself to talking about behavior, then I get to do a few good things. First, I get to say what I mean without a bunch of qualifications. I can say that the business object depends upon the database row without having to describe the cache that sits in between. I can say that history grows indefinitely, even though a program that actually did that would eventually crash.

Second, I get to procrastinate. I can put decisions off until I have enough information to make them. I can implement an object's behavior one way, then measure the system to see if I need to change it.

Third, I get to prove things. There is a reason that mathematicians define integers based on behavior. It's hard to prove things about state. Formal proofs of algorithms is notoriously difficult. But proofs based on behavior are trivial by comparison.

When I explore some techniques for historic modeling in upcoming posts, I'll be talking about the behavior of objects. When getting down to the implementation details, I'll start talking about state. It's the difference between the two that makes these techniques so useful.

Leave a Reply

You must be logged in to post a comment.