In Progress
Unit 1, Lesson 1
In Progress

Processes Everywhere

Video transcript & code

In recent episodes we've been talking about the concept of so-called "process objects", and how they can encapsulate user actions without resorting to "service objects".

In the example that we've been developing, so far we have three external events which feed into our process: a user submitting a purchase order; a callback indicating that shipping has been approved; and a polling job reporting that a the user's payment has cleared.

We could have modeled these as three separate "service objects", one for each "action". But instead, we brought them together into an object that models the entire purchasing process from beginning to end. Handling the events causes the purchase process to advance through four states: ready, pending shipping approval, pending payment, and completed.

On discovering this notion of "process objects", we might be tempted to immediately make a new subdirectory in our application directory, just for process objects. But let's hold off on that for a moment.

In episode #331, we said that process objects really aren't that special. They are just another part of our domain model—they just happen to model a business process, rather than a static element of our domain. The obvious next question is this: where do we draw the line between processes, and static objects?

We've identified some obvious processes. A purchase is a process. An invitation to a new user is a process, that might move through states like "invited", "accepted", and "verified". We've also talked about how bank transactions aren't truly transactional in the real world, and in fact work more like processes.

Then there are concepts which we usually treat more like static entities: things like user accounts, or products, or loan applications.

But a user account might progress from "probationary" to "open" to "closed". A product might go from "planned" to "available" to "canceled". A loan application might move from "blank" to "partially complete" to "pending credit check" to "approved".

The longer we live with many of our domain concepts, the more we realize that they each have their own lifecycles, and can each behave like processes.

Now think about objects in the real world. You probably perceive me as a human object named "Avdi". But biology tells us that in fact, I am a collection of billions of tiny machines, all busily working to sustain and replace themselves in order to maintain the integrity of the whole. If I were to actually be a static object, I would immediately fall apart. In a way, it's less accurate to say that I "am Avdi", and more accurate to say that I am being Avdi. I am a stable process.

In the end, when we look at the world this way, we start to see that it's not so much a dichotomy between static objects and processes. In fact, all objects can be seen as processes that are somewhere on a continuum between "stable" and "volatile".

In addition, we can see objects as falling somewhere on a similar continuum between "short-lived" and "long-lived". An object representing a networking handshake might exist for mere nanoseconds, and only in the context of a single method call. On the other end, some processes may be stable over years or decades.

So in the end, it doesn't make sense to segregate "process objects" into their own directory. Our domain models are full of business processes; some are just more stable than others.

This isn't anything new, either. Alan Kay talked about first envisioning objects as being like individual cells, or tiny computers on a network. Cells and computers are both processes. Seeing our objects as processes of varying stability is really just getting back to the roots of object-oriented design.

This is all very metaphysical. What's the practical value of this observation? Well, next time you're confronted with a difficult question of object modeling, ask yourself these questions:

  1. Can I solve this by identifying an implicit process and embodying it as an object? or
  2. Can I solve this by making an existing object behave more like an process? Can I make it accept notifications of events and move through a sequence of states?

If you find that these questions help you work through an object modeling conundrum, I'd love to hear from you. Happy hacking!