In an interview, Victoria Livschitz touches on a problem that has been bothering me for some time. Notably, "The sequence of the routine itself -- what comes before what under what conditions based on what causality -- simply has no meaningful representation in OO, because OO has no concept of sequencing, or state, or cause."
Case in point. One of the most durable/pervasive uses of OO has been to implement protocol interfaces, standards. For example, EJB, JMS, JNDI, or JavaMail.
It is quite natural to build a protocol interface in objects. Encapsulation, coupling/cohesion, design patterns, etc, are all a natural fit. But you are still left with getting the dialog down and correct. When looking at a set of methods on a session bean, in what order must they be called? Does order matter?
And this can only be tested at runtime. Imagine a Java compiler telling you that you forgot to initiate the connection/session with a HELO to a remote SMTP server, or that you must invoke 'startFoo()' before 'revertFoo()' but may optionally invoke 'notifyFoo()' in between.
At a micro level, this can all be implemented with assignment, if statments, and for/while loops. The logic of process is embedded in the code. And in the case of protocols, this is fine, since protocols rarely change.
But at the macro level, we have tried to reduce our complexity by sequestering logic into a middle tier. But at this level, business requirements reign, and they demand change.
To solve this problem, we have devised rule and process engines that externalize our rules and process so they may be reasoned in a more fitting context. Using this approach, we now have 'system of record' and 'system of process' as first class entities in our architecture.
But if our 'system of process' is malleable and a friend of change, how is our 'system of record' implemented and interfaced with, and does it inexpensively support change?
Lets assume typical EJB/appserver deployments are simply: business logic + data + protocol interfaces.
What happens if you pull the logic out into the process engine, where this engine manages the dialog with various protocol interfaces (and people)?
Are you just left with a container full of objects managing/holding data (that is already sourced from external systems; RDBMS)? How resilient is this container to change? Must I recompile and restart to add a field or relationship? How do I migrate data in the face of larger changes?
Or should data be kept in it's most natural state, leaving the process engine to map this data into and out of various protocol interfaces, be they relational databases, XML stores, workflow portals, or mail servers?