Entity life history patterns

This booklet is published under the terms of the licence summarized in footnote 1.

 

Entity life history patterns

Simple entity life history patterns

Behavioral constraints as event sequences

Behavioral constraints as preconditions

Three-dimensional logical models

Can there really be life after death?

Appendix A: Object-oriented life history analysis in the UK

 

Key terms and definitions

Event

An event is a discrete, atomic, all-or-nothing business service that updates one or more objects, and perhaps refers to the state of other objects. An event is a discrete, atomic, all-or-nothing happening. It updates one or more Objects, and perhaps refers to the state of other objects.

 

Database readers: think of events as database transactions.

J2EE readers: think of events as session beans.

Event impact structure

An event impact structure shows a short-running process, the pattern of objects affected by one event.

State

An object’s memory is often called its state. Every object experiences events and responds to them. Transient objects see only one event at a time, and have no memory of past events. Persistent objects see a stream of events over time, and retain a memory of what has happened.

Entity life history

An entity life history is the behavior of an object, or a class of objects that share the same behavior. The stream of events affecting a persistent object is describable as an entity life history. An entity life history is a fact of life; it happens, whether we document it or not. It is possible for one object to have several parallel entity life histories, but this is not relevant here.

 

The object-oriented principle of encapsulation means that nobody but an object can see its own memory, its own state. So any event that inspects the state of an object must (by definition) appear in its entity life history.

Entity life history diagram

An object¹s entity life history diagram shows a long-running process, the pattern of events that update or refer to the state of an object over its life. Database readers: think of objects as relations or tables. J2EE readers: think of objects as entity beans.

 

There are several ways to document an entity life history. The notations of Mealy, Moore, Harel and Jackson come to mind. This chapter compares and contrasts two styles of entity life history documentation: state transition diagrams (after Moore) and life history diagrams (after Jackson).

 

State transition diagrams are state-oriented. Life history diagrams are event-oriented. Both specify constraints on the sequence of events in an entity life history. Both specify the states an object can be in, the state transitions it can undergo, and the events that cause those state transitions.

 

The most notably difference is that life history diagrams impose the structure of a regular expression (defined later) over the event effects. This makes them harder to learn, but also give some advantages. Pros and cons are discussed at the end of the chapter.

 

For any given software system, its set of entity life history diagrams and its set of event impact structures are isomorphic views - one can be transformed into the other - though it is very rare to find either view completely documented (outside of classroom case studies).

Entity and event modeling

This is an analysis and design method based on iterative refinement around and between three complementary modeling techniques:

A - draw entity-attribute-relationship model

B - draw objects' life histories as entity life history diagrams

C - draw event impact structures

 

The aim is to generate C from B as mechanically as possible, then generate code from C.

Life history analysis

This is the process at B above by which a developer investigates and documents the entity life histories of the co-operating objects that form a system.

 

Students often ask: Can we avoid doing life history analysis? Can we specify the entity model, then directly specify the events in the form of Event impact structures?

 

The answer yes, of course you can. However, there are two good and very different reasons to specify the entity life histories:

  • analysis - knowledge acquisition about events and their effects on objects
  • design - specification of rules for designers and programmers.

Regular expression

The pattern of events in an entity life histories can always been shown using the concept of a formal grammar known as a regular expression.

 

A regular expression is a hierarchical structure composed of sequence, selection and iteration components.

 

The notation used below imposes a regular expression over the event effects. Components in sequence are drawn from left to right; * marks an iterated component; o marks a selected option. 

 

If you don’t have a CASE tool to help you draw entity life history diagrams, you can represent the information in a table as shown below, where sequence is shown top to bottom.

ENTITY LIFE HISTORY: Marriage

Post conditions

Wedding

Status = active

Married Life

* Anniversary

Status = active

End of Marriage

o-- Divorce

Status = historic

o-- Death

Status = historic

Deletion of Marriage Record

Status = null (see notes below)

 

Feel free to redraw the illustrations in UML and send them to me;-)

Order processing example

State transition diagram variant

A state transition diagram is state-oriented. The model builders starts by drawing states as ovals, then adds events as labels on arrows that pass between states, or cycle around the same state. Some notations enclose the event names in boxes, and I have done that below to make comparison between notations easier.

State variable values

You might number the state variable values. However, it is better to provide meaningful text names for the values, since these are useful in displaying error messages at the user interface.

 

An Order in the ‘open’ state may be extended with new Order Items.

An Order in the ‘closed’ state may no longer be extended with new Order Items, but can now be paid for.

An Order in the ‘paid’ state is complete, has reached the end of its natural life.

 

A common and reasonable convention is to write ‘archived’ in the final state. Truly, the final state must be null, the same as it was before the object was created. An Order in the ‘archived’ state has in effect returned to ‘null’ state; it has no record, the data has been deleted.

A state transition diagram excludes invalid events

A Payment event could find an Order in one of the states ‘open’ or ‘paid’. But in these states the event would be rejected, so it does not occur in the entity life history and cannot be documented in the state transition diagram.

A state transition diagram may include non-update effects of events

The concept of state is wider than the value of a state variable. A Payment event could find an Order that is ‘closed’ in one of these two states:

  • amount-owed greater than the amount on this payment
  • amount-owed not greater than the amount on this payment

 

In both these states the event will be accepted and processed, so it does occur in the entity life history and can be documented in the state transition diagram. It appears twice because it has a different effect depending on the state of the object.

Life history diagram variant

A life history diagram is event-oriented. The model builder starts by drawing the pattern of events, using the concepts of a formal grammar known as a regular expression. A regular expression is a hierarchical structure composed of sequence, selection and iteration components.

 

The notation imposes a regular expression over the event effects. Components in sequence are drawn from left to right; * marks an iterated component; o marks a selected option.

The model builder adds state variable values as labels on those event effects that alter the state variable of the object.

Some events advance the state variable; some do not. In a state transition diagram, the latter can be shown on arrows that loop back to the state they start from. In a Jackson strucure, they are shown under an iteration. E.g. See Payment (not enough) above.

 

The corollary is that events that do not advance the state variable should  be shown under an iteration or an iterated selection in a Jackson structure.  But I won¹t pursue the implications of this here.

 

If you don’t have a CASE tool to help you draw Jackson structures, you can represent the same information in a table as shown below, where sequence is shown top to bottom.

ENTITY LIFE HISTORY: Order

Post conditions

Order Creation

Status = open

Order Mutations

* Order Mutation

o-- Item Addition

 

o-- Item Removal

 

Order Closure

Status = closed

Receipt of Payments

* Payment (not enough)

 

Payment (enough)

Status = paid

Order Deletion

 

Microwave oven example

The second example below is borrowed from a chapter by Shlaer (reference in introduction).

State transition diagram variant

It represents an object’s behavior as a unstructured network of nodes (states) connected by arrows (events).

It took a long time to arrange this diagram. No tool has a way to tidy up this kind of diagram so that it will reduce the variation between different designers and also leave the diagram in a presentable state.

State variable values

I have both numbered and named the state variable values because, it turns out, there are fewer state variable values in the life history diagram that follows, and the numbers help to show the points of correspondence.

Action sequences and derivation rules

In this example, the event arrows are annotated with action sequences. Each action must in fact be implemented by sending a output message. The generation of an output message is a kind of derivation rule. So the action sequences are in effect specifications of what I call in these chapters behavioral derivation rules - they describe what the event does and the state of affairs the event leaves behind it.

Superstates

State transition diagrams can become very complex when lots of event arrows go to the same successor state, arising from many prior states. This is not illustrated here, but I note that to simplify such diagrams, David Harel invented the concept of a ‘super state’ for use in Harel Statecharts. The superstate encloses several particular states. Model builders can draw one arrow from the superstate rather than many from its consituent states.

 

A super state in a Harel Statechart normally equates to a ‘posit’ in a life history diagram. See furher discussion below.

Life history diagram variant

The diagram below shows the Shlaer’s entity life history as a hierarchical structure of nodes, with a regular expression imposed over the event effects. To make the two diagrams look more alike, I have not followed the life history diagram convention of qualifying events with different effects at different states by an effect name in brackets.

State variable values

A CASE tool can mechanically assign numbers to the state variable values. Any text description must be added by hand . Curiously, the CASE tool used here has generated only four states rather than six. The tool has spotted some redundancy n Shlaer’s state transition diagram. Two of the states are duplicated.

Pattern recognition

After hierarchical structuring, the diagram turns out to feature one Flip-Flop pattern (door open, door closed) nested within another Flip-Flop pattern (idle, cooking).

Actually, there is a better and more elegant design, involving three parallel Flip-Flop entity life histories maintain three state variables, but we’ll save that for another chapter.

A false economy in notation

Some think the most important criterion for a diagrammatic notation is economy of representation. Absolutely not! This way leads to a cryptic language suitable only for a mathematical treatise.

People do not work like computers. People naturally introduce a great deal of redundancy into their communication; this gives the listener several different chances to recognise what is being said. The need for some redundancy in graphical notations is supported by twenty years experience of those using the regular expression notation in this chapter.

 

Some theoreticians have objected to the hierarchically-nested representation of an iteration shown on the left below; they propose the alternative notation on the right.

All the evidence is that practitioners work best with the notation on the left, because the difference between component types is more visually powerful.

 

(My main complaint about the regular expression notation is that, even after twenty years, I still sometimes fail to spot the difference between a sequence and a selection at first glance. The little circles do not quite mark the difference enough. Putting circle over the corner of the box might work for me.)

Pros and cons of the life history diagram notation

Many years ago, in1986, the UK government commissioned some work to compare and contrast state transition diagrams with life history diagrams. They settled at that time on using the life history diagram notation in the UK’s standard systems analysis and design method. It is worth reviewing some of the arguments in the light of subsequent experience.

Four advantages

Amendment

Because a life history diagram is hierarchical, a CASE tool can redraw and tidy up the diagram automatically after any amendment. A diagram will tend to look the same whoever draws it, and it will always be in a presentable state. 

Completeness

Because a life history diagram is hierarchical, there is space to add detail underneath the event effects. The diagram can easily be annotated with details of the constraints and derivation rules that events apply to attributes and relationships. Thus, a life history diagram is more readily able to combine two elements of an object-oriented design method - a state transition diagram and a class specification.

 

A CASE tool should enable us to document constraints and derivations rules ‘behind’ an event effect, and show it on the diagram only when we ask. 

 

A CASE tool should provide automated assistance for specifying the constraints and derivation rules by offering menus of attribute names, relationship names and action types, automated optimisation/validation of state variable values, and so on.

Validation

The entity life history diagram notation is more obviously comparable with event rules tables. The idea is that every event effect in an entity life history appears also an event effect in an event rules table. So the notation helps people to validate the entity life histories (described in life history analysis) against the event impact views (built in object interaction analysis). A CASE tool can generate event rules tables by reading life history diagrams.  

Requirements capture

The life history diagram notation helps us to recognize standard patterns, by reducing the variation between diagrams drawn by different designers. These patterns that prompt analysis questions. Patterns assist people to discover and specify the business rules of a system.

While it may be possible to develop a catalogue of state transition diagram patterns, I already have a pattern catalogue of life history diagram patterns. Translating these patterns into the form of state transition diagrams would be an interesting challenge.

Four disadvantages

The four disadvantages of the life history diagram notation are significant.

Poor CASE tool support

The validation advantage above has not turned out to be so helpful in practice. People do not normally specify entity life histories and event rules tables to the level of completeness that is necessary to achieve thorough cross-checking and validation.

 

Why? The work is time consuming and no current CASE tools support the cross-validation as well as they should. Don’t blame CASE tool vendors, blame customers for lack of understanding and vision, and for not pressuring the vendors to provide the automated assistance that they need to do their job efficiently.  

Ignorance of the posit-admit-quit technique

I noted that a super state in a Harel Statechart normally equates to a ‘posit’ in a life history diagram. It is always possible, but sometimes very clumsy, to represent an entity life history as a wholly hierarchical regular expression. Sometimes there is a ‘recognition problem’ and you need to quit from one part of the structure (the posit) to another (the admit).

 

Michael: So with "posit, admit, quit", you abandon the well-structured discipline of drawing regular expressions?

Graham: Yes and no. The technique is applied on top of a well-structured diagram, in a disciplined way, such that patterns of Posit. Admit and Quit can be recognised.

 

To prevent clumsiness in drawing life history diagrams you need to understand recognition problems and the posit-admit-quit technique. In the 1980s, the UK government assumed that a large percentage of its systems analysts would have already learned this technique when being trained in structured program design. Sadly, this is no longer true.

 

Today, I see the fact that there are known posit-admit-quit patterns as being an advantage of the life history diagram notation - but I am lonely in this view.

Limited exchange of specifications between CASE tools

A CASE tool should be able to translate a life history diagram into a state transition diagram. However, it cannot do the reverse without a very deep understanding of posit-admit-quit patterns. No CASE tool has this understanding.

Longer learning curve

There is much more to life history analysis than notations. People need to spend two to three days working on case studies to get to grips with life history analysis, to grasp how life history diagrams and event rules tables work together as orthogonal views of a single software system specification. People using the life history diagram notation need to spend an additional half a day or so learning the rules of the posit-admit-quit technique.

 

Why is this a problem? In the 1980s, even a ‘basic’ certificate in systems analysis required an intensive four-week course.  The UK government developed their standard systems analysis and design methodology for people with a year or two’s experience after their basic training, and at least two weeks additional training was expected.

 

Since then there has been a downward pressure on training time. Many employers do not ask for systems analysts and designers to have any professional training in systems analysis and design at all. They ask only for experience in using a specific programming technology - be it Oracle, SAP or C++. Under pressure of time, teachers teach only the symbols of the diagram notations.

Almost nobody teaches ‘how’ any longer - nobody teaches analysis and design techniques. 

‘Why are professional standards not insisted upon in IT?’

president of the British Computer Society at a conference in March 1997.

Whatever the reason - it is a fact. One reason is the failure of our unversities to teach what professional systems analysts ought to know.

The failure of university courses to teach systems analysis

Some university courses teach ‘proper’ software engineering - the writing of operating systems, compilers and process control systems. These tend to teach object-oriented methods and dismiss Enterprise Applications as trivial. More practical university courses concentrate on relational theory, because it leads quickly to practical databases and programming languages.

 

Neither kind of course covers the everyday problems of Enterprise Applications analysts and designers, because these everyday problems fall outside the scope of the theories.

Analysis by pattern recognition

To date, many people find the entity life history dimension of the Business Rules model is the most obscure and difficult. But it turns out that life history analysis is especially valuable in requirements elicitation, because there are many generative patterns in life history diagrams that make you ask questions about the users requirements. You do have to ask and answer these questions, whether you document the answers in the form of life history diagrams or not.

 

Patterns are recognizable shapes that assist analysis and design. Most people are mostly interested in entity models. There are indeed many patterns to be found in entity models, but to end this chapter, here is a simple pattern in a more obscure face of the modeling cube.

 

Flip-Flop is a pattern that is especially common in process control systems, where a machine must be turned on and off in response to some received events.

Fig. 2f

 

It is easier to recognise standard patterns if you use a structured notation for life history diagrams.

 

A constructive pattern is one you can reuse and build upon. Flip-Flop is a constructive pattern that is especially common in  process control systems, where a machine must be turned on and off in response to some received events. See the next chapter for further discussion.

 

A generative pattern is one that leads you to ask questions and refine the design. Flip-Flop is a generative pattern. E.g. you should ask of any iteration: What stops it? See the next chapter for the resulting transformation.

Conclusions and remarks

Many notations can be used to represent entity life histories.  In the end, the pros and cons of state transition diagram and life history diagram notations are so well balanced that most people prefer the notation they learn first. Sadly, I do have to choose one notation for this series of chapters.

 

The RAP group is more interested more in techniques and analysis questions than in notations. There is more to life history analysis than other techniques. This means there is both more to teach and more to learn. The longer learning curve is seen by some as a problem, but should instead be seen as an opportunity. It means there is a real prospect of being able to educate analysts, designers and software engineers beyond the primitive stage that current training courses take them to.

 

Michael: I'm not sure that software engineers get much training in regular expressions or entity life histories in most courses. Generally, they will get that in a compiler course, but most do not take those courses, and no tie in will be made to Enterprise Applications anyway. Reading 'Shlaer and Mellor', or 'Barker', you find that they dismiss the value of state-transition for Enterprise

 

Applications, concentrating instead on factory process control and so on. This is a shame. Also, most folks working in our business don't even have a computing science degree, let alone a software engineering degree, so they have learned primarily coding languages, with only an off chance that they even had to take a database course to graduate.”

 

Graham: Yes. And the only way to address this problem through professional training.

 

The ‘more to learn’ I mentioned above is partly composed of analysis patterns. This series of chapters introduces only a few simple patterns. life history analysis based on patterns is exciting because it helps you solve a wider variety of software design problems than other analysis techniques (such as entity relationship modeling, relational data analysis or data flow analysis). And it solves them more fully, providing a more complete path from requirements specification to program code.

 

Patterns help to compensate for lack of training time. Patterns gathered from experience can be presented in a catalogue, so that people who have learned only the notation can gain deeper insights into what they are doing. Patterns also enable the posit-admit-quit technique to be taught more easily.

 

This chapter illustrates a nine simple patterns in entity life history analysis, and lists some analysis questions that the patterns prompt you to ask.

  • The One-State Life pattern
  • The Random Mutation pattern
  • The Aggregate Maintenance pattern
  • The Life after Death pattern
  • The Death by 1000 cuts pattern
  • The Business Thread pattern
  • The Missing event pattern
  • The Sudden or Delayed event pattern
  • The Flip-Flop pattern

The One-State Life pattern

Any persistent object in a software system must first be created and will eventually be deleted. So the basic entity life history is a sequence of these two events. We’ll start with an example drawn from the presentation layer. After you make a mistake, the error message box that pops up your screen probably has a very short life; it is destroyed when you click on the OK button.

 

People don’t normally think of On Display and Deleted as being states. You don’t need a state variable to tell you whether an object exists or not, you can test this more directly.

Q) Given a two-event sequence, are any other events constrained to happen between the two events?

 

You often discover a non-state changing iteration of events. E.g. Users may repeatedly ‘click’ in the wrong part of the screen, causing the system to sound a warning beep.

 

The rule is: state before an iteration = state after each iterated component. So a Click in Wrong Place event leaves the object exactly as it found it, in the state ‘On Display’. So the object still has a one-state life. Again, you do not store the state variable of an object like this, you only test whether it exists or not.

The Random Mutation pattern

In the business services and data services layers, information objects are created and deleted to reflect what is happening to entities in the real world.

 

The simplest kind of information object experiences nothing in between creation and deletion, but a random mixture of events that replace the values of different attributes. You may show this as an iteration selection in the middle of the One-State Life Pattern.

State variable values have been optimised thus:

·      unify the state before an iteration with that after each iterated component

·      unify the states after events which end options under a selection.

 

These rules mean any kind of Mutation event leaves the state of the information object exactly as it found it - ‘Present’. The only other state variable value is NULL - the state of an object before and after its period of existence. Setting the state variable to NULL on the diagram implies that all the variables of an object instance are deleted at this point, and perhaps that its unique key variable is available for reuse.

Minimising the documentation of states

Where an event does not update the state variable value, you can leave the state off the diagram, simply assume the prior state is carried forward. You can assume the last event in the entity life history diagram returns the state to NULL. Then, where an object has only one state, you can discard the state-variable.

 

Thus, the information object above needs no state variable. You can evaluate any preconditions by asking whether the object (or its primary key) exists in the system.

The Aggregate Maintenance pattern

The maintenance of an aggregate (be it members of a set, money in a bank balance, or any other cardinal amount) normally looks like the Random Mutation pattern, but with the addition of cardinality constraints. There are several questions. Ask of an aggregate:

Q) What events increment or decrement the aggregate?

 

Show these events under the iterated selection.

Q) Do these events increment or decrement by one at a time? or by a variable amount?

 

Show this in the operations allocated to the event effects.

Q) Is there any cardinality constraint on an increment event?

 

Show this as an operation underneath the event effect of the form: Fail unless value after increment < upper limit value.

Q) Is there any cardinality constraint on a decrement event?

 

Show this as an operation underneath the event effect of the form: Fail unless value after decrement > lower limit value.

Given the earlier rules, you don’t need a state variable. You might try to represent a limit constraint as a state transition, shown the object cycling through states such as ‘empty’ and ‘full up’, but this leads to overelaborate entity life histories, so don’t do it.

Q) Is there any sequential constraint between the increment and decrement events?

Do you have to make a deposit before a withdrawal? This sequential constraint belongs in the entity life history not of the parent class that maintains the aggregate, but of a child class that represents an individual item. If there is no such child class, because users don’t need to track individual items, then the constraint can only appear as cardinality constraints in the entity life history of the Aggregate Maintenance class, as mentioned above.

The Life after Death pattern

Many popular implementation technologies, visual programming environments, database application generators and CASE tools are built on the assumption that:

most if not all information objects have a one-state life, and are deleted on death

few business constraints require you to test the state of objects

automatic referential integrity rules will be enough.

 

Most database management systems can automate the application of referential integrity rules. These work by testing whether an information object exists or not. If all information objects have one-state lives of the kind shown so for, then ‘referential integrity rules’ will give you much of what you need to constrain the database.

 

The vendors of database management systems tend to play down state-changes in any case study they develop. They give entity life history analysis little attention in any method they teach.

 

The trouble is: the four assumptions don’t usually hold for the ‘interesting part’ of the system. Most information objects do undergo one critical state transition - from live to dead.

 

The birth and death of objects is a major feature of Enterprise Applications analysis and design.

Q) Given a death event: Does the event automatically delete the object from the system?

If no, you will need to specify a Business Thread of at least three events.

 

It is usual for an information object to ‘die’ a long time before the decision to delete it from the system. So every interesting object has at least two states, alive and dead. This single state transition is enough to limit the usefulness of some database technologies.

 

The Death-Deletion gap makes it hard for an application generator to produce the system you want, because it cannot distinguish live objects from dead ones. There are two problems.

  • SQL enquiries (of the kind you can easily generate from the database structure) will return a lot of data you aren’t interested in. You want to store dead objects for historical analysis, but you don’t want them to appear in the screen displays shown to end-users who are trying to do their day-to-day business. The longer the system runs, the more that reports and displays will become cluttered up with irrelevant data.
  • Referential integrity rules (of the kind you can easily generate from the database structure) don’t what you want. An application generator may be able to apply ‘restrict’ and ‘cascade’ rules automatically to physical deletion events, but not to logical death events, which is often what you really want. E.g. a customer’s orders will be cancelled on deleting the customer record, but not on the customer’s death.

The Death by 1000 cuts pattern

Sometimes the rule for a death event hitting an Aggregate Maintenance object is that the object can only be deleted if it has no children left; otherwise it must wait until it loses all children. The Aggregate Maintenance pattern must be extended using the Death by 1000 cuts pattern.

Every selection in an entity life history is governed by a condition. Normally this condition tests the event type and the condition is apparent from the names of the events in the selected options. In this case however, the same event starts both options of a selection, so an additional condition must be applied.

 

The object acts as a ‘monitor object’ for a Death event. It decides whether a Death event has one effect or another by inspecting the number of objects remaining in the aggregate. This might mean searching through a set, or it might means testing a derived total attribute; the choice is food for further discussion in the chapter ‘Avoiding double trouble’.

 

Much the same pattern can be used to model any case where an object may be deleted on its death, but only if a condition applies; otherwise the object must wait until the condition does apply.

The Business Thread pattern

The Business Thread pattern is any sequence of three events or longer. Suppose you do not delete information about a Marriage until one of the partners dies, then the Marriage entity life history might look like this.

 

In practice, it is rare to find unbroken sequences of more than two events. The sequence may be broken in various ways. So a simple Business Thread is a generative pattern.

Q) Given a Business Thread: Can the last event happen without the second-last?

 

If yes, you may transform the Business Thread using a null option, to form the missing event pattern below.

The Missing event pattern

When you answer yes, a tool could automatically insert a selection with a null option that enables you to by-pass the second-last event.

The resultant diagram is itself a generative pattern.

Q) Given a Missing EVENT: Does the null option determine the effect of the following event?

If yes, then you may transform the Missing event pattern by dividing the effects of the following event, to form the sudden or delayed death pattern below.

The Sudden or Delayed event pattern

When you answer yes, a tool could automatically divide the following event into two effects and remove the null option, leaving you to add different operations. This diagram below shows two options, one a short way to deletion, the other a longer way.

 

Every selection shown in an entity life history is governed by a condition. Normally, as here, this condition tests the event type and it is apparent from the names of the events in the selected options. In this case, the selection tests for Death or Divorce.

 

There is another kind of selection, not so visible in the entity life history perspective. A Marriage object act as a ‘monitor object’ for a Death event. It decides whether a Death event has one effect or another by testing the current value of its state variable, joined or asunder. This selection is made visible in the event rules table for a Death event.

 

Where there is a long sequence of events, repeated occurrences of the Sudden or Delayed event pattern may turn the structure into the Daisy Chain pattern discussed in a chapter not included here.

The Flip-Flop pattern

The flip-flop pattern is a two-state cycle, represented as an iterated sequence.

The Flip-Flop pattern is common in process control systems of the kind often featured in books on object-oriented design. Even though there are many circumstances that may arise to complicate the basic shape, you can build a working process control system using little more than this pattern.

Flip-flop as a generative pattern

A generative pattern is one that prompts you to ask questions and perhaps transform the pattern into a different shape. Given a Flip-Flop pattern you should ask:

Q) What stops the iteration?

 

There must be some kind of death event. This may not be a significant question in a process control system, where objects live until the computer is switched off, but it is vitally important in Enterprise Applications, where objects can die within the life span of the system.

 

Enterprise Application designers tend to be heavily concerned with birth and death events. (Yet case studies in books often gloss over the complex effects of death events.)

Fig. 2g

 

The answer here of course is a person’s death event. A cycle-terminating event like this generates further questions. You should ask:

Q) Does the death event interrupt the last flip-flop cycle?

 

To represent this, you should choose between one of four patterns shown in a chapter not included here. (They are not shown here because some of these patterns involve ‘backtracking’, a technique not explained here.)

 

Then if the object may have children, that is lower-level objects connected by a one-to-many relationship in the entity model, you should ask:

Q) Should the death the event be broadcast from this object to children of this object?

 

If the answer is yes, this will involve drawing the Broadcast pattern in an event impact structure (see chapter ‘Discrete event models’) and further analysis of the effects of the death event on child objects.

Q)  Does the flip-flop reveal child objects that users want to keep a history of?

If the answer is yes, then the entity model must be extended.

Flip-flop as a constructive pattern

A constructive pattern is one you can reuse and build upon. Flip-Flop is a constructive pattern that is especially common in  process control systems, where a machine must be turned on and off in response to some received events.

Fig. 2f

 

There are many ways to build upon a pattern in an entity life history diagram. One is to add enquiry effects of events.

 

I should distinguish events from enquiries. Events update at least one object, enquiries don’t. But an event can hit several objects. It may update one object and make an enquiry upon another, perhaps to check it is in a valid state or perhaps to retrieve some data needed for a derivation rule.

 

The diagram below illustrates how the Flip-Flop pattern might be extended between state-change events to include the enquiry effects of event X under iterations.

 

This object acts as a monitor object for event X. It decides whether event X has one effect or another by inspecting the current state of its stored data. The enquiry effects do not advance the state variable because its values have been optimised using the rules given earlier. (???)

 

To include enquiry effects or not? Whether you should or should not show the enquiry effects of update events in an entity life history diagram has been debated for nearly thirty years.

 

Keith Robinson used to teach that an event occurs in the entity life history of every object it refers to, as well as the entity life histories of every object it updates. In other words, every event effect in an event rules table appears in an entity life history. He claimed that classroom teaching is simpler and students learn quicker if they follow this rule.

 

Keith believed that objections to including enquiry effects in practical system documentation would disappear with the advent of adequate CASE tool support for drawing the diagrams (for automatically optimising state variable values, and for generating event impact structures) and with better teaching of how to design the most economical set of entity life histories.

 

Sadly, Keith’s hopes have not been borne out.  Later chapters discuss how to omit enquiry effects from entity life history diagrams without losing the specification information.

Conclusions

This chapter has summarised some basic entity life history patterns. To go further I must enter the territory where you have to draw more than one entity life history to solve the problem, and I look at how entity life histories are co-ordinated in the chapter ‘3-way conceptual modeling’.

 

This chapter compares and contrasts different approaches to behavior analysis or life history analysis. It illustrates various levels of completeness to which life history analysis can be taken.

Clashing paradigms

Two life history analysis techniques have been developed almost independently. The inheritance paradigm emphasises the analysis of hierarchical structures of super and subclasses, and reuse by inheritance. Object-oriented authors such as Booch (1986) and Meyer (1988) specify a software system as a set of inter-related classes, encapsulating processes around abstract data types.

 

The entity life history paradigm emphasises the analysis of events input to a software system and the state-changes they trigger in persistent objects. Authors such as Jackson (1975) and Hoare (1985) discussed ways of specifying a software system as a set of cooperating sequential processes or entity life histories.

 

Each paradigm has desirable properties that the other lacks. So can we develop a behavior modeling approach that combines the ideas of Grady Booch and Michael Jackson? an approach that regards cooperating objects as interacting entity life histories?

 

It might be thought that there is a clash between the OOP notion of a class and the notion of an entity life history. In fact, the formula OO class = entity life history does work well for modeling behavior in the Business Rules layer.  However there is sometimes a clash between the notion of class in the business rules layer and a class in other layers. You may need to merge or divide  classes when designing the user interface or database layers.

 

At a lower level of granularity, there is sometimes a clash between the OOP notion of an operation and the entity life history notation of an event effect. This clash is explored in this chapter.

An entity model

The case study is very simple. The diagram below shows the classes and relationships of the entity model, and lists the main events that affect it.

An event impact structure

You can specify in an event impact structure and/or event rules table:

·      the objects it hits, and the path by which it finds them

·      its behavioral constraints - preconditions testing the states of objects

·      its derivation rules - changes to objects’ attributes and relationships

 

Many of the events are trivial (Customer Registration for example). Two of the most interesting events are Customer Withdrawal and Payment, both of which might delete a Customer. I take the opportunity to illustrate two styles of event impact structure below.

 

The Customer Withdrawal event fires up two operations, one in Customer and one in Store. Note that the operation on Customer contains a case statement; it only deletes the Customer if there is no outstanding debt. Note that the event only fires the enquiry operation on Store if this condition is true.

 

The Payment event fires up an operation in an object in each of three classes. Again, the operation on Customer contains a case statement; it only deletes the Customer if it has been withdrawn and there is no outstanding debt. And note that the event only fires the enquiry operation on Store if the Customer is this condition holds.

 

Factoring out a common operation

During the analysis, it becomes apparent that the Customer Withdrawal and Payment events share a common action on Customer (Delete) and a common effect on Store. They both check to see the Store is open before they delete the Customer. This can be factored out into an operation called §Store.LossOfCustomer. The operation is a very simple precondition test:

                Store.LossOfCustomer

                Fail Unless StoreState =open

Showing conditional invocation by correspondence arrows

An alternative representation is to show each event effect explicitly, which enables a more precise correspondence arrow to be drawn.

 

Note (above and below) how the correspondence arrows show the fact that the Payment event only fires the Store.LossOfCustomer operation if a selection condition applies in the operation on Customer.

Life histories

In theory, one can complete entity and event-oriented behavior modeling by following the rule that every event effect shown in an event impact structure corresponds to an event effect in a life history diagram. You can work from the event impact structures to the life history diagrams or vice-versa.

 

Given that all the event effects are documented in event impact structures, a reasonable question is: Do we have to draw the life history diagrams as well?

 

The answer is that the event impact structures shown above were not in fact completed before the life history analysis. They are only shown first in this chapter for the sake of illustration.

Neither view has precedence. In practice one develops both views in parallel.

 

It is true however that model builders very rarely complete the life history diagrams to the same level of detail as the event impact structures.  A more reasonable question is: How can we get the benefits of life history analysis without documenting every entity life history in full?

 

First of all, your CASE tool should be doing all the tedious parts of the work for you, generating event impact structures by reading life history diagrams and vice-versa. OK, so your particular CASE tool doesn’t actually help you to do this. What can you do by hand?

 

Entity life history analysis is very much easier and more natural if you draw first-cut event impact structures beforehand. Think of life history analysis as a supporting technique for sorting out the business rules and constraints where objects in an event impact structure have state-changes beyond the ‘insert’ and ‘delete’.

 

Try it this way. Start the event impact structures before life history analysis. Draw an event impact structure to specify the correspondences between all the objects referred to by the event.

Assume the default precondition for an object (other than an object created by the event) is ‘Fail unless object exists’. Then, only document the entity life history of an object that has more than one state.

 

This section describes five different degrees of completeness for the documentation of an entity life history. Practitioners may decide for themselves at which degree of completeness they will stop.

1 Show only state-change effects of events

An object’s state is composed of specific values for its attributes, relationships and state variable. A minimalist view of life history diagrams is that they are a form of state-transition diagram, showing only those event effects that change an object’s state variable. Thus, the entity life history of Customer might be drawn as below.

 

 

A Customer in the ‘active’ state may place Orders and pay for them.

A Customer in the ‘debtor’ state may no longer place Orders, but can pay for past ones.

A Customer in the ‘NULL’ state has no record, the data has been deleted.

 

You can assign numerical values to successive states in the entity life history. However you will usually want to provide meaningful text names for the states, since these are useful in displaying error messages at the user interface.

 

You only need to show state variable values on an entity life history diagram under events that change the value, and you can suppress the NULL value from under the last event.

2 Show other effects of state-change events (in the same entity life history)

The Payment event impact structure earlier showed that the Payment could find the Customer in one of three states:

·      active

·      debtor, and debt greater than this payment

·      debtor, and debt not greater than this payment.

·       

Only the last of these has been shown as a state-variable-updating effect in the entity life history so far. What about the ‘null effects’ or ‘enquiry effects’ of the Payment event? You could show them in the object-oriented entity life history as below.

 

By showing the Payment event before and after Customer Withdrawal, this diagram says that an Payment is valid at any time. However, the Payments, being shown under simple iterations, do not advance the state variable.

 

Showing the enquiry effects of a state-change event in an entity life history gives three benefits. It prompts you to:

ask if the enquiry effects update the object’s state (they do in our example)

bring the life history diagrams into closer correspondence with the event impact structures

develop a more complete object-oriented specification.

3 Add state-testing events

What about events that do not alter the state of an object, but must test its state variable? A behavioral constraint on the Order Placement event is that the Customer must not have been withrdawn yet. You can show this precondition by placing the Order Placement event in the Customer entity life history between Customer Registration and Customer Withdrawal, where it may happen any number of times.

 

By showing the Order Placement event before Customer Withdrawal, but not after it, this diagram specifies the rule that an Order Placement is invalid after Customer Withdrawal. Again, there are three advantages of showing such a state-testing event in an entity life history. It prompts you to:

ask if the enquiry effects update the object’s state (they do in our example)

bring the life history diagrams into closer correspondence with the event impact structures

develop a more complete object-oriented specification.

4 Add derivation actions

Further analysis may show that what seem to be only enquiry effects do in fact update attributes or relationships of the object. For example, see the actions allocated in the diagram below. Rather than worry about whether an event has an update effect or not, it is easier to follow the rule: include all the effects of one event in an entity life history, both update and enquiry. An exception is discussed as a simplification six in the next chapter.

 

I am very close to now to a complete, graphical and object-oriented specification of all the processing of one class. However, some events have not been included. So far I have left out events that do not test or set an object’s state variable, but do change an attribute or relationship of the object.

5 Add state-independent events that trigger derivation actions

A ‘state-independent event’ neither tests nor updates the state variable. It is valid at any time. You may however include it in an entity life history to specify the update of an attribute or relationship. For example, you may include the Customer Name Change event in the entity life history as shown as below, at the expense of some minor duplication.

 

 

Actually it is untrue that the Customer Name Change event does not need to test the state of the Customer object. It needs to make the most basic test of all, that the Customer exists (its state variable is not null). However, it is harmless to omit such trivial events from entity life history analysis, as suggested in the next chapter.

By the way, the minor duplication of Customer Name Change event effects could be resolved by creating a parallel aspect class just for Customer Name Changes, but this would be more trouble than it is worth in such a simple case.

 

A life history diagram specifies constraints on the sequence of events in an entity life history. This chapter distinguishes an enterprise-level event from a system-level event. It describes ways to simplify life history diagrams, and to specify constraints in them by allocating preconditions rather than spelling out event sequences.

Entity life histories

State: Every object experiences events and responds to them. Transient objects see only one event at a time, and have no memory of past events. Persistent objects see a stream of events over time, and retain a memory of what has happened. An object’s memory is often called its state.

 

Entity life histories: The stream of events affecting a persistent object is describable as an entity life history. An entity life history is a fact of life; it happens, whether you document it or not. An entity life history is the behavior of an object, or a class of objects that share the same behavior. It is possible for one object to have several parallel entity life histories, but this is not relevant here.

 

Events in an entity life history: The object-oriented principle of encapsulation means that nobody but an object can see its own memory, its own state. So any event that inspects the state of an object must (by definition) appear in its entity life history.

Life history diagrams

Life history analysis investigates and documents the entity life histories of the cooperating objects that form a system. There are various ways to document an entity life history. Some are limited to recording events and states. A simple state transition diagram specifies the states an object can be in, the state transitions it can undergo, and the events that cause those state transitions.

 

A life history diagram is like a state transition diagram. They both specify constraints on the sequence of events in an entity life history. But the former can more easily be annotated with details of constraints and derivation rules that events apply to attributes and relationships.

Three questions

An enterprise-level event happens in the real world. A system-level event is what the system gets to hear about. The first question is:

Should we document enterprise-level events in a life history diagram?

 

An entity life history is what happens. A life history diagram is only a description of what happens. The second question is:

Should we document every event that occurs in an object’s entity life history in that object's life history diagram?

 

It is in theory possible to specify every structural and behavioral constraint as a sequence of events in a life history diagram (other chapters support this assertion). So, the third question is:

Should we try to specify every structural and behavioral constraint as a sequence of events in a life history diagram?

 

The answers are given below, along with five ways to simplify life history diagrams.

1 Omitting trivial events

Consider an event that does nothing but overwrite some descriptive text attributes of an object with new values, and is not constrained by any precondition (other than the object exists of course). This event definitely occurs in a system-level entity life history of the object, but is it worth documenting in a life history diagram?

 

No. The purpose of life history analysis is to document non-trivial update events and constraints upon those events. There is little point in drawing life history diagrams to specify update events that are trivial and unconstrained. This is the kind of event an application generator can generate from an entity model.

 

So, you can omit from a life history diagram any event that is valid at any time during the life of the object (that is, between creation and deletion) and is so trivial that it does not affect any other object (so does not appear in any other entity life history).

 

E.g. you could reasonably omit the Customer Address Change event from the Customer life history diagram.

 

Caveats

If you generate event specifications from life history diagrams, then you will not generate specifications for any of the trivial events. You might get around this by adding all the trivial events into the life history diagrams at the very end of analysis, after all state-changing and state-testing events have been fully analysed.

 

By the way, once you have used the facilities of an application generator to generate the code for trivial update events, you have the problem of turning off or constraining the processes it generates. This mix-and-match approach to design often turns out to be harder than coding all the update processes by hand.

2 Allocating range constraints

Consider the constraint that an event should not take an object’s attribute over a limit, or outside a permitted range. This is definitely a constraint on an event in an entity life history, but is it worth trying to document the constraint as a sequence of events?

 

No. Model builders who try to turn the cardinality of an attribute or relationship into a state variable, tend to produce a highly overelaborate set of life history diagrams.  You should instead allocate a precondition under the relevant event, allocating an action of the type: Fail unless precondition true.

 

E.g. an Order Placement event must fail unless the Order Value is greater than $100.

 

Where a constraint refers data from several objects, which entity life history contains the constraint? The general principle is to place a constraint in the entity life history that owns the  attribute whose range is being tested. Consider three constraints on an Order Placement event

Fail unless OrderValue (OrderQuantity * StockUnitPrice) > $100

 

OrderQuantity is an attribute of Order. StockUnitPrice is an attribute of Stock Type. But the constraint is on OrderValue, this is an attribute of Order, so the precondition belongs in the Order entity life history.

Fail unless TotalUnpaidOrders < 5

 

The constraint is on TotalUnpaidOrders, this is an attribute of Customer, so the precondition belongs in Customer entity life history.

Fail unless OrderValue + CustomerDebt < CustomerCreditLimit

 

OrderValue is an attribute of Order. CustomerDebt and CustomerCreditLimit are attributes of Customer. The constraint is on the difference between the Limit and the Debt, this difference is an attribute of Customer, so the precondition belongs in the Customer entity life history.

 

By the way, I do not say here whether the ‘derived attributes’ such as OrderValue or TotalUnpaidOrders are stored or derived when needed. It is in practice often necessary to store redundant data in order to save redundant enquiry processing.

 

Caveats

There is no caveat. The only reason to turn the cardinalities of attributes into the state variables of entity life histories is to show it can be done. This is an interesting exercise from an academic point of view, and it is explored in appendix 99.

3 Constraining the objects that receive an event

Consider a broadcast event that starts at a parent object and travels down a one-to-many relationship where it updates some, but not all, of the children.  If every child receives the event, then the child entity life history must include both update and non-update effects of the event. The non-update effect is an enquiry revealing the object is in the wrong state for the update effect.

E.g. Every Order gets to hear of the Customer Deletion event. This has an update effect on unpaid Orders but no effect on paid ones. So, the Customer Deletion event appears twice in the Order’s life history diagram, having an update effect before Payment and an enquiry effect after it.

 

However, it is easier to postulate a fetch relevant child action that skips over children on which the event has no effect. This means you can omit the non-update effect from the child’s life history diagram. You can show the selection condition by qualifying the name of the update effect with a role name.

E.g. Only unpaid Orders get to hear of the Customer Deletion event. So, the event appears only once in the Order’s life history diagram, before or instead of Payment, and is qualified in brackets thus Customer Deletion [unpaid].

 

Caveat

Later, it may turn out that non-update effects are update effects after all, so have to be reintroduced into the life history diagram.

4 Allocating date or time constraints

Consider the constraint that event B must be rejected until enough time has elapsed since event A. There is definitely a sequence of three events in the real-world. The enterprise-level entity life history contains a sequence of three events: event A, Elapsed Time event, event B. But is it worth including the Elapsed Time event in a system-level entity life history?

 

No. You can instead deduce whether the Elapsed Time event has occurred by a derivation rule when the next event happens. You allocate a precondition under the date-constrained event that says: Fail unless event B date < or > derived date.

 

E.g. Consider the constraint that a Payment event must be rejected unless four days have elapsed since the Order Placement. There is definitely a sequence of three events in the real-world: Order Placement, Fourth Day, Payment. But the system-level life history diagram can be reduced to two events.

 

Caveats

If you generate an event specification for the Date event by reading event names from the life history diagrams, then the event specification will not show all the objects that are accessed.

A date event should be drawn explicitly in any life history diagram where it has an update effect.

5 Omitting enquiry-only effects of events

Remember that any event that inspects the state of an object must appear in its entity life history. Consider an event that updates one object and needs to make an enquiry upon another, perhaps to check it is in a valid state or perhaps to retrieve some data needed for a derivation rule. The event clearly does occur in the entity life history of the enquired-on object. But is it worth documenting this in its life history diagram?

 

Perhaps not. You can instead allocate an enquiry invocation action under the update effect in the life history diagram of the updated object. Examples are discussed below under the heading of referential integrity.

 

Caveats

If you generate event specifications by reading event names from the life history diagrams, then the event specifications will not show any of the objects that are only accessed for enquiry. Both the invocation of the enquiry, and the enquiry operation itself, must be included within the event specification.

 

Later it may turn out the enquiry operation is an update operation after all, so has to be reintroduced into the life history diagram.

Objections to including enquiry effects in practical system documentation should disappear with the advent of adequate CASE tool support for drawing the diagrams, for automatically optimising state variable values, and for generating event rules tables; and with better teaching of how to design the most economical set of life history diagrams.

Referential integrity in life histories

Referential integrity constraints are intended to guarantee the integrity of parent-child relationships. The question here is: How are these constraints documented in life history diagrams?

 

It seems intuitively obvious that any event that affects a relationship between a parent and a child must have an effects on, appear in the life history of, both parent and child. But if an event only makes only an enquiry upon an object, then there is the possibility of making the optimization mentioned above, of omitting that event from the life history diagram of the enquired-on object. Let us consider two cases, a restricted creation constraint and a restricted deletion constraint.

Allocating restricted creation constraints

Referential integrity means a child cannot be created or tied to a parent unless that parent exists. There is a constrained event sequence here. The parent creation event must occur before the child creation event. You may show this in the life history diagram of the parent. Normally the child creation event is iterated somewhere between the parent’s creation and deletion events.

 

However, you may instead allocate a precondition in the child’s life history diagram under its creation EVENT: Fail unless parent exists. You may then omit the child’s creation event from the parent’s life history diagram.

 

Where the target implementation environment is a database that can enforce referential integrity constraints and you intend to switch this function on, then you might choose to rely on the database to apply the constraint.

Caveats

If you generate an event specification for the creation event by reading event names from the life history diagrams, then the event specification will not show the parent object that is also accessed.

 

Later, it may turn out that the child’s creation event (e.g. Order Placement) must test the state of the parent rather than its presence or absence (e.g. the Customer must not be suspended). Or it might have an update effect on the parent such as adding to a total (e.g. the CustomerDebt).

 

These things turn out to be true so often that this is the weakest of the proposals for simplifying life history diagrams. It is generally easier and safer to teach the rule: A parent’s life history diagram should include the birth and death events of its children. You may easily remove events that are proven to have no update or enquiry effect at the very end of life history analysis.

Allocating restricted deletion constraints

Referential integrity means a parent cannot be deleted while any children are attached to it. This leads to four basic specification options for any parent deletion event.

  • Cascade deletion; the parent takes all its children with it; this only works if the user is happy to lose the children.
  • Set null deletion; all the children are cut from the parent: this only works if the relationship is optional at the child end.
  • Swap parent deletion; all the children are swapped to another parent; this only works if another parent can be nominated on the parent deletion event.
  • Restricted deletion; a parent’s deletion event is constrained not to happen until all its children have been deleted, perhaps one-by-one.

 

There is a constrained event sequence in a restricted deletion. The child deletion event must occur before the parent deletion event. You may show this in the life history diagram of the child; you add the parent deletion event at the very end.

 

This is a correct but counter-intuitive form of specification. You may instead allocate a precondition in the parent’s life history under its deletion EVENT: Fail unless no children exist. You may then omit the parent’s deletion event from the child’s life history diagram.

 

E.g. a Store Closure event is constrained not to happen until all its Customers are deleted.

 

How is the ‘no children’ test made? Where the target implementation environment is a database that can enforce referential integrity constraints, then you might choose to rely on the database to apply the constraint in the database layer, and simply test the result in the business rules layer.

 

If it is impossible to make the ‘no children test’ without attempting to access the children, and you want to reduce databases accesses, you can optimize by specifying that the parent object maintains an ExistingChildren total, and tests this as a precondition before its own deletion.

Caveats

If you generate an event specification for the deletion event by reading event names from the life history diagrams, then the event specification will not show any child objects that are accessed to test their existence.

 

Restricted deletion doesn’t work if the restriction applies to the logical death event of the child (where the child is not deleted but merely moved to a new state ‘dead’). In this case one can refine the optimization above by asking the parent to maintain an ActiveChildren total rather than an ExistingChildren total

 

It may turn out that the parent’s deletion event deletes its children after all, so it is really a cascade deletion, and it does belong in the child’s life history diagram.

Conclusions

The three questions were:

Should we document enterprise-level events in a life history diagram?

Should we document every event that occurs in an object’s entity life history in that object's life history diagram?

Should we try to specify every structural and behavioral constraint as a sequence of events in a life history diagram?

 

This chapter has answered ‘No’ to all three questions. It has described five ways to simplify life history diagrams, and to specify constraints in them by allocating preconditions rather than spelling out event sequences. I recommend the first four simplifications; they are reasonably robust. The last is a risky optimisation. Don’t do it unless you have considered the consequences.

 

A small case study shows how the three conceptual modeling techniques complement each other, and something of how to develop an event-oriented specification alongside an entity-oriented one.

 

The chapter discusses the birth and death events of child objects, and the analysis of a structural relationship to reveal one of the following patterns in the life history of the parent object: Aggregate Maintenance, Swap Parent, or Flip-Flop

Child birth and death events

Consider the birth and death events of the child entity in this tiny two-entity system.

Entity state model

ENTITY: School

Invariants

School Name

 

Pupils

= total number Pupil entities

ENTITY: Pupil

School Name

= identify of a known School

Pupil Serial Num

 

 

You can draw the Pupil Registration and Pupil Deletion event rules tables following the patterns for child birth and child death events given earlier. An event rules table shows all the object instances affected by one event. An arrow shows how an object is identified, by the event parameters or by another object. You can add the details of preconditions and post conditions.

EVENT: Pupil Registration (PupilSerialNum, SchoolName)

Entities affected

Preconditions

Post conditions

School

Present

Pupils = Pupils +1

Pupil

Present

Tied to School

 

EVENT: Pupil Death (PupilSerialNum)

Entities affected

Preconditions

Post conditions

Pupil

 

Present

Deleted

       

o-- at school

School

 

Pupils = Pupils - 1

A numbered operation is a single processing step. Operations include constraints, guards or preconditions. The Pupil Deletion event will fail unless the Pupil and the School exist.

The aim here is to paint an impressionistic picture rather than explain all the details. The point is: you can specify all the implementation details, operations and rules fired by one event on a diagram like this. Further, a tool can generate most of these details from the entity life history diagrams by following a mechanical transformation procedure.

 

Object interaction analysis takes an event-oriented view. Entity life history analysis takes an object-oriented view of the same specification.

From structural relationship to Aggregate Maintenance life history pattern

An object-oriented entity life history shows all the events affecting one class. It gives a dynamic view of the class in terms of the events that update its attributes and relationships, and the sequential constraints on these events.

Q) Given a child class: do the birth and death events of the child refer to the state of the parent?

 

If yes, copy the child birth and death events into the entity life history of the parent. E.g the School entity life history includes Pupil Registration and Pupil Deletion.

Q) Given a one-to-many relationship: Is the relationship monogamous - only one child alive at one time, the rest being historical?

 

If yes, the entity life history of the parent should include the child’s birth and death events under the Flip-Flop pattern. An example appears later.

Q) Given a one-to-many relationship: Is the relationship polygamous - many children alive at one time?

 

If yes, the entity life history of the parent should include the child’s birth and death events under the Aggregate Maintenance pattern. For example:

 

The named boxes at the bottom of an entity life history are the ‘event effects’, or simply ‘effects’. Each event fires a ‘method’ in an object, having the effect shown.

 

The label in the bottom-right-hand corner shows the value of the state variable after the event effect. After ‘optimising’ the values using the standard rules in chapter 2d, the entity life history is a One-State Life, so the state variable is not required.

 

The numbered boxes beneath the effects are operations. In OO programming, you would code an operation as a single processing step within the implementation or ‘method body’.

 

The numbered list shows the executable operation types. You can draw operation types from a generalised list of the operation types that are implementable across a known range of target implementation environments.

 

The aggregate being maintained is the set of active children, Pupils. The entity life history of the child class is very simple.

 

From structural relationship to Swap parent life history pattern

Looking at a class relationship model, the full nature of the relationships is obscure.

 

If the relationship is mandatory, and the child object has a changeable parent, this implies a Swap Parent event. E.g. you may discover there is a Pupil Transfer event.

EVENT: Pupil Transfer (PupilSerialNum, SchoolName [new])

Entities affected

Preconditions: Fail unless…

Post conditions

Pupil

 

 

Pupil swapped from old school to new school

--->

School [old] (lose pupil)

 

Pupils = Pupils - 1

School [new] (gain pupil)

School not full

Pupils = Pupils + 1

 

The event affects two different objects of a class (School) in different ways. Objects of the class play different roles with respect to the event. Roles are shown by adding a role name in square brackets; this tells you how the event finds or recognises this particular object instance, as opposed to any other object of the same class. The different effects are further described with an effect name in round brackets.

Class name

Entity role name

event effect name                    

School

[old]

(gain Pupil)

School

[new]

(lose Pupil)      

 

Each event effect appears in both event-oriented and object-oriented views. So how does this Pupil Transfer event appears in the entity life history view of the classes in the event rules table? Normally, a swap parent event makes a predictable appearance in the entity life histories. You have to copy the swap parent event twice into the entity life history of the parent, the two effects being on different objects of the same class.

 

Entity roles and event effects

Notice that in the entity life history for a School, the event effects are named in the opposite way from in the event rules table.

Event name

Even effect name

Entity role name

Pupil Transfer

(gain Pupil)

[old]

Pupil Transfer

(lose Pupil)

[new]

From structural relationship to Flip-Flop pattern

There are two kinds of relationship that prompt you to draw a Flip-Flop pattern in an entity life history:  an optional relationship with an independent child, and a monogamous relationship.

It turns out that one relationship is a refinement of the other. When you change the data structure, the entity life histories of existing classes retain exactly the same shape, but with different operations.

From optional relationship to Flip-Flop pattern

Suppose the relationship from Pupil to School is optional at the child end. Looking at the class relationship model, the reason is obscure. You should ask questions about it.

 

A Pupil can be transferred from one School to another in two ways: either suddenly by one transfer event; or slowly, by withdrawing a Pupil from one School and reinstating the Pupil later in another School. So, you discover that the relationship is initially tied, then may be repeatedly cut and tied.

 

You cannot model the sequential constraint between Pupil Withdrawal and Reinstatement in the entity life history of the parent (School), since the behavior of one Pupil is interleaved with the behavior of all the other concurrent Pupils.

 

However, you can model the sequential constraint in the life of the child using the Flip-Flop pattern.  In this case the Flip-Flop pattern is complicated by the addition another optional event type (Pupil Transfer) that may occur between cycles.

 

The Pupil entity life history below shows the constraint that a Pupil Reinstatement event can occur only after a Pupil Withdrawal event, and two Pupil Withdrawal events cannot happen in a row. You now need to allocate state variable values, say, ‘registered’ and ‘out of school’.

 

 

From optional relationship to monogamous relationship

Q) Given a Flip-Flop pattern: Does it reveal a child object that users want to keep a history of?

 

If yes, then you should add the class into the class relationship model. E.g.

From monogamous relationship to Flip-Flop pattern

The relationship under School is polygamous, there are many concurrent children. The entity life history of the parent (School) contains the birth and death events of its child (Pupil) under the Aggregate Maintenance pattern. You can only show the birth-death sequence in the life of a child class.

 

The relationship under Pupil is monogamous, there is only one active child at a time. So the birth-death sequence appears not only in the life of the child class, but also in the life of the parent class. The entity life history of the parent (Pupil) contains the child’s birth and death events (in reverse order in this case) under a Flip-Flop pattern. 

Conclusions

The purpose of this chapter is to paint a broad picture showing how you can bring the three dimensions of a conceptual model into harmony. I’ve only scratched the surface here of the many patterns you can recognise. Let me review some of the ideas in this chapter, especially with regard to graphical representation of a system specification.

A class relationship model shows the cardinality of associations

A class relationship model gives a static picture of classes in terms of the associations that relate two classes to each other. A class relationship model is very useful in systems development, but it does not tell the whole story. The constraints it shows are mainly to do with the cardinality of objects at either end of a relationship. You cannot show all of the other constraints that end-users want to place on data processing.

 

Most notably, you cannot show the time dimension. A class relationship model is a static view of a system, a snapshot at one moment, it does not show how an object instance changes over time, or how a relationship changes over time.

An event rules table shows the corresponding effects of one event

You can best visualise and recognise the corresponding effects of an event by representing them graphically in an event-oriented diagram. An event rules table shows all the object instances affected by one event. You can add implementation details.

Event-oriented and object-oriented views must correspond

You can view the effect of an event on a class from two perspectives, that of the transient event and that of the persistent object. So each event effect in an event rules table can be transformed into an event effect in an entity life history, and vice-versa. This is enormously helpful in systems analysis, in teaching, and in developing CASE tool support.

An entity life history shows the events affecting one entity

An entity life history shows all the events affecting one class. It gives a dynamic view of the class in terms of the events that update its attributes and relationships, and the sequential constraints on these events. You can add implementation details.

A conceptual model can be implemented

Conceptual specification of requirements should precede physical design. In other words, an analyst should sort out the user’s business needs before worrying about a specific user interface technology, database technology or programming language.

 

But it is very, very important that anyone who proposes a conceptual form of specification should demonstrate it can be carried forward through physical design to implementation. It is important to know that there are techniques, supportable by CASE tools, that help us transform between entity life histories and event rules tables, and transform either or both into program code. In the end, you may code from either perspective.

Various coding styles

The more effort you put into analysing object behavior and interactions, the easier it is to implement the system. But object-oriented analysis does not have to lead to object-oriented programming. How you cut the code is a different level of concern. It doesn’t matter so much whether you write the program code in the form of object-oriented class specifications or event-oriented procedural routines; you can do either.

 

A short story about modeling constraints in structural and behavioral models.

This chapter is an entertainment with some serious purposes. The story may give you some insights into the analysis and specification of constraints on entity models and behavioral models (entity life history diagrams and event rules tables). It alludes to the scheme for business rules introduced by the Business Rules Group.

 

The story also forms a backdrop to questions that I believe should be addressed by the OMG in looking to improve business rules specification in UML - whether to assist the Model Driven Architecture initiative or just because it is a good idea.

A few terms and concepts

An event is a discrete, atomic, all-or-nothing happening. It updates one or more objects, and perhaps refers to the state of other objects. An object¹s entity life history diagram shows a long-running process, the pattern of events that update or refer to the state of an object over its life. Database readers: think of objects as relations or tables. J2EE readers: think of objects as entity beans. An event¹s event rules table shows a short-running process, the pattern of objects affected by one event. Database readers: think of events as database transactions. J2EE readers: think of events as session beans.

 

For any given software system, its set of entity life history diagrams and its set of event rules tables are isomorphic views - one can be transformed into the other - though it is very rare to find either view completely documented, outside of classroom case studies.

 

Entity and event modeling is an analysis and design method based on iterative refinement around and between three complementary modeling techniques:

·      A - draw entity-attribute-relationship model

·      B - draw entity life history views and diagrams

·      C - draw event impact views and structures

The aim is to generate C from B as mechanically as possible, then generate code from C.

The story

David Hay (best known as author of "Data Model Patterns" ISBN -932633-29-3) suggested to me recently that UML cannot model a "restricted deletion" constraint. This could lead us into a debate about whether the "aggregation" concept in UML models this constraint or not, and I agree with Martin Fowler that aggregation is a poorly-defined concept. But I¹d rather let it lead me into telling a story about the life after death paradox.

Life is taxes, death and more taxes

The taxman may refer to your estate after your death.  Below, in the entity life history diagram that shows your life:

·      sequence is shown top to bottom

·      iteration is shown with an asterisk

·      event names are in capitals

·      post conditions (changes to attribute values) are in the right-hand column.

 

ENTITY LIFE HISTORY: Life

Post conditions

BIRTH

Status = alive

LIFE

* TAX

reduce CurrentAccountBalance

DEATH

Status = dead

LIFE

* TAX

reduce EstateAccountBalance

You can easily redraw the events and states of this diagram as UML-style entity life history diagram, but please allow me to use the more emailable diagram format above, a kind of 'Jackson structure'.

 

You may be a little worried by taxation after death. For many years, I was worried, in a more academic way, about events that refer to the state of an object after it has died, and the paradox this leads to when modeling the case where a "death event" has the effect of deleting the object's state record.

Structural terms, facts, constraints and derivations

In the case study to be considered, structural terms include Parent, Child and NumberOfLiveChildren.

  • A structural fact is that Children are born of Parents.

In the very strange world of the case study, an invariant Constraint is that a Child must have one and only one Parent. The entity model shows the Invariant Constraint as a one-to-many relationship.

  • Entity model: Parent ---<* Child

Obviously, you could draw this structure using UML. One of the irritating features of UML is the way it uses an asterisk to show both an interleaved many, where the many live in parallel, and an iterated many, where each cycle is constrained not to start until the previous one has finshed. Older notations used a crowsfoot for an interleaved many, and an asterisk for an iterated many, but I doubt the OMG will ever improve UML to distinguish these concepts.

  • A structural derivation is that Parent.NumberOfLiveChildren = total of Child objects with Status = alive.

Behavioral terms and facts

Behavioral terms include the names of events. A birth event creates an object; the object¹s state is now recorded and available for inspection or update. A death event usually signals the end of updates to an object’s record. Other events update or refer to objects’ states.

 

Behavioral facts include that Child Birth events affect both Children and Parents. The event rules table below is annotated with the effects – attribute value updates.

EVENT: Child Birth

Entities affected

Preconditions

Post conditions

Parent object

 

add 1 to NumberOfLiveChildren

Child object

 

Status = alive

Behavioral constraints

Many behavioral constraints can be modeled by drawing the valid sequences of events in entity life history diagrams. For example, birth precedes death.

ENTITY LIFE HISTORY: Child

Post conditions

CHILD BIRTH

Status = alive

CHILD DEATH

Status = dead

 

ENTITY LIFE HISTORY: Parent

Post conditions

PARENT BIRTH

Status = alive

LIFE

* LIFE EVENT

o-- CHILD BIRTH

add 1 to NumberOfLiveChildren

o-- CHILD DEATH

take 1 from NumberOfLiveChildren

PARENT DEATH

Status = dead

The 'o' marks an option of a selection. The events under the iterated selection (or random mixture) in the Parent entity life history diagram do not advance its state variable, but do update the attribute NumberOfLiveChildren.

 

After transforming the entity life history diagrams into event rules tables, constraints on (preconditions of) the event will appear as conditions that test the state variables of the objects.

a restricted birth constraint

The Invariant Constraint that a Child must have one and only one Parent is not enough, that Parent must be alive when the Child is born. The event rules table for the Child Birth event shows this behavioral constraint as a fail condition in square brackets.

EVENT: Child Birth

Entities affected

Preconditions

Post conditions

Parent object

Status = alive

add 1 to NumberOfLiveChildren

Child object

 

Status = alive

If an event discovers an object in the wrong state, then the whole event (session or transaction) is aborted, not just the operation on the object. So, if the Child Birth event discovers its Parent object in the dead state, then the Child Birth event (session or transaction) is aborted.

a restricted death constraint

In the strange and cruel world of the case study, there is a terrifying "restricted death" constraint. A Parent object cannot die until all its Children have died. The Parent's death event refers to the state variable of the Child, so must appears in its entity life history diagram, after the Child's own death event.

ENTITY LIFE HISTORY: Child

Post conditions

CHILD BIRTH

Status = alive

CHILD DEATH

Status = dead

PARENT DEATH

 

 

The event rules table for the parent's death event looks like this

EVENT: Parent Death

Entities affected

Preconditions

Post conditions

Parent object

Status = alive

Status = dead

 

-->* Child object

Status = dead

 

 

If the Parent Death event discovers a Child object in the alive state, then the whole event is aborted, not just the operation on the Child.

a restricted deletion  constraint

Death and deletion do not necessarily happen at the same time. Death is a constraint on further changes. Deletion is the removal of the object¹s record from the system. Logically speaking, objects live forever. Once created, an object's record persists for all eternity. So, deletion is an act of vandalism to the data record.

 

But in practice, we do mangle logical and physical models into one. Suppose a side effect of the Child's death event is to delete the Child's state or database record. The constraint becomes: a Parent cannot die until all its Children have been deleted.

 

Strangely, the shape of the entity life history diagrams are unchanged, though they now show an event occuring in the entity life history diagram of the Child object after it has disappeared. Only the annotation against the Child's death event is modified.

ENTITY LIFE HISTORY: Child

Post conditions

CHILD BIRTH

Status = alive

CHILD DEATH

delete state

PARENT DEATH

 

 

The shape of event rules table below for the parent's death event is also unchanged. Only the fail condition on the Child object is modified.

EVENT: Parent Death

Entities affected

Preconditions

Post conditions

Parent object

Status = alive

Status = dead

 

-->* Child object

object missing

 

Wierd. Truly wierd. But this process will works when coded.

life after death

For a long while I lived uncomfortably with the paradox that entity life history diagrams can include posthumous events after the object has been deleted. The general model for this being:

ENTITY LIFE HISTORY: Object

Post conditions

OBJECT BIRTH

Status = alive

OBJECT LIFE

* LIFE EVENT

Update state

OBJECT DEATH

Delete state

OBJECT LIFE AFTER DEATH

* POSTHUMOUS EVENT

 

multiplicity constraints

Having drawn an event rules table, you can annotate any number of constraints on it. That was the common practice in the 1980s.

e.g. one might annotate [Fail Withdrawal event unless Dollar Amount < 100]

 

For many years however, Keith Robinson and others were interested in trying to generating constraint rules from the shapes of entity life history diagrams.  Keith's CASE tool automated most of the work of transforming entity life history diagram models into event rules tables. He generated not only the event rules tables from the entity life history diagrams, but also the constraint rules from the entity life history diagram shapes.

 

In UML terms, you might say we didn¹t document “guard conditions” on entity life history diagrams, and our aim was to generate them on the event rules tables.

derivation of multiplicity constraints from child states

Every time you see an attribute that holds a sum or total value, you can analyse further to model the discrete items in that sum. Choosing to model at this lower level of detail or not is one of the many decisions you have to make during analysis and design.

e.g. A stock quantity total implies the presence of stock items. If the stock is of nuclear missiles, you'll want track each one. If the stock is of nails, then you won't, unless you are very very mean.

 

An entity life history diagram constrains the sequence in which events can occur. It used be an article of faith for us entity life history diagramers that *every* constraint can be shown in an entity life history diagram as a sequence of events. We didn't want to document constraints any other way.

e.g. A constraint that there can be no more than 500 Items in a Stock Pile can be viewed as a constraint that only 500 Stock Items (be they Nuclear Missiles or Nails) can be in a position in their entity life history diagram after their Stock Receipt event and before their Stock Issue event.

 

I once wrote a chapter (so academic I was too embarassed to show it to anybody) to demonstrate that a constraint of the kind  "Fail Withdrawal event unless Dollar Amount < 100" was really a constraint on events in the entity life history of a single dollar. At least, I think that's what it demonstrated. And it took me many pages to make a point I now skip over in a paragraph.

the pandora's box of business rules

About 1992, the Union Bank of Switzerland (UBS) ran a competition for application generator vendors to implement a case study that featured a small entity model with some complex business rules, and some recursive processing. E.g. if there is insufficient stock to fill an order, then it is filled partially, and it spawns a new order for the outsanding amount.

 

The competing vendors built a naive (CRUD) database solution in a day or two that completely failed to implement the required business rules.

 

Keith Robinson, also in a couple of days, built an object event model that contained all the required business rules. Sadly, Keith died shortly afterwards.

 

Some time later, Christoph Henrici of UBS called me over to have a look at Keith's Entity and event model. It was very complex, perhaps the most complex object event model I have ever seen. But it wasn't so much the complexity Christoph was concerned with. Christoph had noticed that Keith had resorted to annotating a constraint on an entity life history diagram of the kind:

   [Fail unless attribute = value]

 

Shock. Horror. Keith had documented a constraint on an entity life history diagram, instead of either drawing out a sequence of events (the academic way), or simply adding the constraints as an afterthought into the event rules table (the practical way).

 

Keith¹s little "cheat" opened the pandora's box of business rules to me. I started to experiment by annotating various kinds of business rules on the entity life history diagrams.

a multiplicity constraint

Using Keith's cheat, you can rework the case study above by omitting the posthumous events from the Child entity life history diagram, and attaching a constraint to the Parent¹s death event thus:

   [Fail unless NumberOfLiveChildren = 0]

 

But that total attribute is derived data. Some people are foolishly determined to remove all redundant data from their models. Suppose the Parent does not maintain an attribute that records the NumberOfLiveChildren?

a set-level constraint

We can be systematic about representing the "restricted deletion" rule in the Parent's entity life history diagram, without having to show posthumous events in the Child¹s entity life history diagram, by annotating the Parent¹s death event thus.

   [Fail unless Child set is empty]

 

This implies that a Parent knows the set of its Children. This is intuitively obvious, but contrary to the relational paradigm, and that's an argument for another time.

 

The constraint tests a property of a set. Whenever all the children of a parent are the same in some way, then that property applies to the set or the parent who owns the set. This is a transitory state of affairs, since any of the children may change, get out of step with the rest. Nevertheless any constraint that tests that a condition applies to all members can be phrased as a test of the whole set.

Conclusions and remarks

The story above helps to illustrate several points. It is clear that to generate code from model diagrams, you have to annotate the diagrams with business rules in one way or another.

 

The Object-Oriented Design paradigm is good at interfaces (signatures anyway) not so good at business rules (semantics). The strength of entity and event modeling is the weakness of Object-Oriented Design, and vice versa.

 

The OMG's Model Driven Architecture (MDA) now needs an adequate way to specify business rules. But adequate doesn¹t mean simply that it must work - it has to be fit for purpose. I believe there are some questions that must be addressed, and discuss those elsewhere.

 

For now, notice how malleable the concepts of business rule specification are:

·       every Invariant Constraint can be recast as a behavioral constraint of one or more events

·       a repeatedly-defined behavioral constraint may perhaps be more economically expressed one Invariant Constraint in an entity model

·       sometimes, a constraint on the value of an attribute may be recast as a constraint on one or more state variable values, and vice versa.

 

And notice that every constraint mentioned in the story is a precondition of an event, not just one operation. If an event discovers an object in the wrong state, then the whole event is aborted, not just the operation on that object. This was one of the ‘awkward’ questions at the end of volume 1.

 

P.S. A reporting or enquiry-only transaction cannot enforce any rule. However, it can detect and select objects for the later application of an update transaction which does apply a rule.

 

A tribute to the late Keith Robinson.

It is almost certainly true that the longest continuous object-oriented research and development programme in the world was started by Keith Robinson in 1977 at Infotech. After Keith’s death in 1993, the development was carried forward by John Hall of Model Systems and I (Graham Berrisford) who now work for Seer Technologies.

1977: Keith published a chapter in the Computer Journal proposing an object-oriented program design method for database systems (not called that of course).  Keith started from Michael Jackson’s earlier suggestion that the variables and processes of each object type could and should be encapsulated in a discrete processing module.  An additional idea was to use the state variable of an object in validation of updates to that object.

1979: I helped Keith develop his proposals into a 10-day course called 'Advanced System Design' based on three techniques:

·         Relational data analysis: Keith taught this as a technique to decompose the required system inputs and outputs (in what we might now call the UI layer) into entity types for behavior analysis in what we might now call the business services or data services layer. 

·         Life history analysis: Keith taught this as a technique to discover the behavior of each entity type and document it in a entity state machine diagram.  He favoured using regular expressions as the notation and called them life history diagrams after Jackson I think.

·         Object Interaction structures: Keith invented and taught these to document how objects exchange messages in order to complete the processing of an event (one event may synchronously update several objects, and/or need to be validated against the states of several objects). 

Keith’s three-dimensional approach to conceptual modeling is now the norm in modern development methods.  But there was a lot more to his method than notations, and some of the ideas he taught to do with scheman evolution are still ahead of the game.

By the way, many years before Yourdon abandoned data flow diagrams, Keith advised against top-down decomposition.

1980: Keith’s course disappeared when his employers went into liquidation.  Not along after this, Keith helped John Hall to develop an analysis and design method for the UK government. SSADM version one was built on around database modeling techniques and incorporated object-based process analysis and design techniques.

Keith and John deemed object Interaction structures impractical for use by database programmers, but included life histories as an analysis tool for discovering processes and business rules. They assumed it was obvious that each life history or entity state machine could be transformed into a discrete program module using Jackson’s technique of program inversion (more widely known then now).

Unfortunately, version two of SSADM was developed by people who did not understand that life histories were a program design technique.  The ground that was lost was not recovered for some years.  And many still believe to this day that the main program specification technique in SSADM is data flow diagrams!

1983: Keith invented 'effect correspondence diagrams' (hereafter ‘event models’) to replace object Interaction structures. The former are simpler than the latter, but equally formal.  They suppress the detail of message-passing (which might be done in various ways) but show the essential correspondence between ‘methods’ in different objects affected by one event.  The most wonderful feature of the diagrams is that they transform equally well into either object-oriented or procedural code.

1986: I tested event models with Keith and John until all were confident they could be adopted by the UK government.  We worked hard to develop rules for mechanically transforming the entity state machine view in the life histories into the object interaction view in the event models.  Keith tested these transformations by developing a CASE tool.

At the same time, Keith and I also proposed separating the business services layer from the data services layer by means of a process-data interface (perhaps coded as SQL views), so you can generate code directly from the event models, careless of the database designer’s implementation decisions or the database management system.

All these proposals were adopted by the UK government for SSADM version 4 in 1989. But they are still not realised today in CASE tools as well as they should be.

1991: Keith worked out a way to detect and document reuse between events in entity state machine diagrams.  The result is a network in which events invoke superevents, which may invoke other superevents and so on. This network can be generated by a CASE tool from the entity state machines.

Keith knew then that SSADM had all the armoury required to be an object-oriented method for database systems, save for two problems.

·         To avoid the confusion that existed (and still exists) in object-oriented methods between UI layer objects and business services layer objects, designers needed to separate the layers of the 3-tier processing architecture.

·         The representation of inheritance in entity state machines needed further research.

1993: Keith and I wrote the book 'Object-Oriented SSADM' (published after Keith’s death by Prentice Hall) mainly to establish two ideas: the importance of separating the layers of the 3-tier processing architecture, and the use of the superevent technique to maximise economy and reuse of code within the business services layer.

1994: I published a chapter in the Computer Journal that showed how the benefits of inheritance (reuse and extendibility) can be achieved through modeling entity state machines for the 'parallel aspects' of a class.

1995: John Hall did most of the hard work necessary to test, demonstrate and establish the above ideas, and more of his own, for adoption by SSADM version 4.2.

 

 

References

Ref. 1:   “Software is not Hardware” in the Library at http://avancier.co.uk

 

Footnote 1: Creative Commons Attribution-No Derivative Works Licence 2.0

Attribution: You may copy, distribute and display this copyrighted work only if you clearly credit “Avancier Limited: http://avancier.co.uk” before the start and include this footnote at the end.

No Derivative Works: You may copy, distribute, display only complete and verbatim copies of this page, not derivative works based upon it. For more information about the licence, see  http://creativecommons.org