The Pattern of Perception consists of a player that has an interface with an incoming and outbound pipe, a set of eyes, a Strategy which produces objectives, and a set of hands. Apparently, there is not a lot to abstract here because each of these objects has a distinct, well defined responsibility.
Or is there something under the surface? Because let’s see here, the eyes for example take information from one space and produce information in another space. The strategy takes the output of the eyes and produces information in the space containing the objectives. The hands do something similar. Both pipes of the interface do the same. So actually, these objects have a lot in common. And what is more, we have already made an abstraction that applies to all of them, remember?. . .
*Every single object we have been talking about is a behavior process!*
Ah, but then what we should do now is to model behavior processes. Once we have them stabilized in our minds and then in code, implementing the rest of the parts should be more straightforward.
> This onion is full of layers!
Note here how the principle of not writing code right away is at work.
As we saw before, a behavior process is a function embedded in an information space. The function takes a position vector from the space it is embedded in, chooses a direction in which to move, and produces a vector which represents how much it wants to move.
Should we explicitly model an information space and position vectors? For now, the answer is no. Doing so could cause us to translate the language of our domain into an abstraction capable of holding anything we throw at it, and as a consequence we run the risk of losing some of the ability to concretely describe our problem. Thus, while we will not create classes such as `InformationSpace` at this time, we will however model everything else to be a good reflection of them.
Do you remember the discussion, a few chapters earlier in the book, about whether behavior processes travelling in an information space end their existence because they finally evaluate or because of an unhandled exception? That is one of the details we have to consider now. Fortunately, it is not as thorny as it seems. In Smalltalk, an unhandled exception is a problem, and as such it should not happen. Because the context in which we have to make this design decision, we have no choice other than to assume a model in which standalone behavior processes *do evaluate*.
> See how easy that was? Scary, huh?
Also, did you notice the distinction we just made? We said that *standalone* behavior processes will evaluate to something. But what would happen if the behavior process is not standalone, meaning that it does not correspond to a Smalltalk process? What does that mean to begin with? Well, one interpretation could be that **the player queries its behavior processes because its design goals ask for a specific composite behavior which is best induced by controlling the sequence in which each of the behavior processes behave more tightly**. This means that our design has to accomodate multithreaded and singlethreaded players.
At first this may seem like an overblown requirement, but I am sure you will be able to think of instances in which you behave one way or the other. As the point of the pattern of perception is to allow us to model our own behavior, then this level of flexibility is truly a desirable feature to have.
Nevertheless, it may feel as if it will cause lots of code to appear. And yet, that just does not need to be the case. A forked Smalltalk process running in the behavior process could simply reuse the code that allows the player itself to query the behavior process in the first place, so this should not be hard to do.
What are we going to do with the information space in which the behavior process moves? We said we do not want to explicitly show that we are thinking about information spaces because that would allow too much of an arbitrary abstraction to shine through. So now we need to hide that a bit without lying too much. How are we going to tackle this? Well, we could talk in terms we can expect others to be very familiar with. For example, what Smalltalk construct is similar to what we want to do? Where in Smalltalk does it happen that there is a map between some input objects and some output objects? The point of a behavior process is to implement behavior, right? So what is the Smalltalk construct that allows behavior to occur?…
Of course! In Smalltalk, *the only thing we can do is to send messages!*
Therefore, we will use the word `sender` to implicitly talk about the source of position vectors, and the word `receiver` to talk about whoever receives the displacement vector from the behavior process.
This looks almost too easy. But consider the many pages and the amount of effort we had to go through to reach this place! It just seems simple now because it is becoming obvious that the amount of code we will have to write is very small — which is exactly the point of not writing code right away.
What other names will behavior processes have to know? Well, in order to make housekeeping easier, there should be an instance name for any embedded process running inside a behavior process. Borrowing from the circuit analogy we discussed earlier in the book, we will call this process the `signal`. To be able to stop a signal gracefully, we will also let behavior processes know whether their `signalShouldEvaluate`.
[…]