This post is also available in: Nederlands (Dutch)
In a previous post (The Essence of OO) I talked about two patterns in modelling complex systems that I consider to be the most important, the active/passive pattern, and the time inversion pattern. In this post more on the first, and this time the pattern is described in a pattern template.
A domain model will become large and very complex. The intent of the model is to capture the domain, that is: reflect the real world. This model should be functional when very small, but be willing to grow, indeed to be infinitely scalable. However, in order to avoid a model that is unmanageable we should not make the fundamental error of trying to model the domain as close to the real world as possible. A simple trick is to turn active and passive around: active objects in the real world are modelled as passive, indeed even almost devoid of complexity in the sense of behaviour or responsibilities. Passive objects in the real world on the contrary are modelled as active, taking initiatives. The responsibilities endowed upon them are precisely those activities that, in the “real” world, are done with them. This will help in realising the intent (this is another aspect of turning-around).
Also Known As
- The World of Roger Rabbit
- Activity inversion
- Looking-glass world
A person pays a bill. He owns an account to pay bills with. The person is the active object in the real world. He pays the bill by opening or accessing the account, creating a transaction, telling the transaction the amount that he copies from the amount contained in the bill, as some other information. And finally he tells the transaction to go ahead. He is a very complex object, with many responsibilities and many relations with other objects. The objects bill, transaction, account, are passive. In fact they contain only the information (data) necessary for the person and usually contain little responsibilities.
There are many passive, exceedingly simple objects (i.e. an Account), and few active, exceedingly complex objects (i.e. a Customer). Usually the active objects correspond to actors in the use cases, or external agents or triggers. The passive objects are data containers, with information used in a business process.
The sequence is also rather critical: first do this, then do this. This is called process brittleness. The process is not easily changed, in fact resists change. The few active objects are strongly coupled to a lot of passive objects (typically more than three) with which they perform all kinds of tasks. These tasks usually entail little more than changing values (data) in these objects.
The system can capture the business problem domain reasonably well when still small, but as the domain grows, that is the model of the business domain in the software, it becomes increasingly difficult to manage, until expanding the domain model becomes virtually impossible. All kinds of dependencies arise. The model collapses under its own weight.
The Active Passive pattern describes the world, or complex systems, by employing two rules:
- Objects that are active in the real world (machines, systems, persons, committees) are modelled as passive, that is they do not initiate actions themselves, and any responsibility they have (and usually they have responsibilities) are delegated to other objects.
- Objects that are passive in the real world (documents, cars, products) are modelled as active, that is they initiate actions, take responsibilities upon themselves to reach a business goal. They typically delegate most of the actions needed to finish a business process to other active objects.
Inversion of activity turns activity and passivity around. In the example: the person has almost no responsibility. Instead the bill has the one main responsibility in this context, namely to “pay himself”. The bill starts the entire process of paying by contacting the person (the bill has presumably been created by someone, and this someone told the bill: “I want some money from this person.” The bill only needs to ask the person for one thing: an account payable. After receiving this account he proceeds by telling the account to create a transaction for himself. The bill is done now, the chain of responsibility has been transferred to the account. However, account does not hold this for long. He creates a transaction for the bill, and subsequently tells this transaction to go ahead. All the rest is done by the transaction. A simple rule of thumb is that any responsibility of an active object in the real world can be relocated to a passive object in the model.
A well-known variant of this pattern is the Expert Pattern, first described as such by Craig Larman in his book on [amazon_textlink asin=’9332553947′ text=’UML and Patterns’ template=’ProductLink’ store=’reflektis-20′ marketplace=’US’ link_id=’4158c5dc-3df8-11e7-9af7-55efd60c4ba7′].
This pattern is usually combined with the Time Inversion Pattern.
The distribution of complexity over the model is more balanced. Some objects are rather passive but are usually linked to several other objects. Some objects are rather active but linked to few others. This way there are not complexity hubs in the model. Processes are more demand-chain and more easily changed. Processes are not the source for the structural model, but rather the responsibility of few key objects (like “bill” in the example above). This recurs in the way the domain model structure comes into being, by employing the Time Inversion Pattern.
The Active Object pattern should not be confused with this pattern. This is a pattern that is mainly used to model objects that contain their own thread of control, to be used in concurrent systems. For the Active Object pattern you can read more here.
This pattern is usually applied together with the Time Inversion pattern.
There is a strong relation between this pattern and CRC sessions. In CRC sessions workshop participants play the role of objects in the customer domain. The facilitator usually emphasises the need to choose objects in the domain that are usually considered passive.