a service oriented design pattern finite state machine behaviour

8
A Service Oriented Design Pattern - Finite State Machine Behaviour Model Some Context Services tend to pass data around, as in Data is transmitted and Behaviour is deployed. We are getting to a stage where the contract on a service can be described well enough as a schema (say an XSD) in that the structure of the elements is understood and that facets on those elements can tie it down enough for a decent representation on 'both ends'. Putting to one side the service description language bindings, the use of XML and a canonical schema has, all in all, greatly aided integration between systems. If you make some concessions to the technology in your Domain Model then this can actually work pretty well. Indigo is building on this by concentrating on a 'Data Contract' part of the Service description, and with a nod towards versioning and the like. But Behaviour descriptions are a lot less flushed out, in that walking up to a Service and figuring out what is does is a completely different level of problem than describing a Data Contract using an open set of standards. A lot of this is to do with how Data tends to evolve at a lot slower rate of change than the rules and processes that make up the behaviour; data does tend to stick around a long time and databases tend to like it that way. As Behaviour code can change much more often and be 'unclosed' in it's effects, then it breaks often compatability and the like; some people describe this as 'coupling' and it's been around in terms of how to design class hierarchies long before SOD(*3) came along. The reason something like document/literal is so sensible is that it steps back from enforcing a set message transfer mindset of transporting an object instant from one side of the world to the other and goes more into the client being able to reinterpret or chicken-peck bits of what they receive and understand. This 'View' on the message data and how it

Upload: rajchanchal

Post on 10-May-2015

1.070 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: A Service Oriented Design Pattern   Finite State Machine Behaviour

A Service Oriented Design Pattern - Finite State Machine Behaviour Model

Some Context

Services tend to pass data around, as in Data is transmitted and Behaviour is

deployed. We are getting to a stage where the contract on a service can be

described well enough as a schema (say an XSD) in that the structure of the

elements is understood and that facets on those elements can tie it down enough for

a decent representation on 'both ends'. Putting to one side the service description

language bindings, the use of XML and a canonical schema has, all in all, greatly

aided integration between systems. If you make some concessions to the technology

in your Domain Model then this can actually work pretty well. Indigo is building on

this by concentrating on a 'Data Contract' part of the Service description, and with a

nod towards versioning and the like.

But Behaviour descriptions are a lot less flushed out, in that walking up to a Service

and figuring out what is does is a completely different level of problem than

describing a Data Contract using an open set of standards. A lot of this is to do with

how Data tends to evolve at a lot slower rate of change than the rules and processes

that make up the behaviour; data does tend to stick around a long time and

databases tend to like it that way. As Behaviour code can change much more often

and be 'unclosed' in it's effects, then it breaks often compatability and the like; some

people describe this as 'coupling' and it's been around in terms of how to design

class hierarchies long before SOD(*3) came along.

The reason something like document/literal is so sensible is that it steps back from

enforcing a set message transfer mindset of transporting an object instant from one

side of the world to the other and goes more into the client being able to reinterpret

or chicken-peck bits of what they receive and understand. This 'View' on the message

data and how it can be interpreted may keep the contract loose enough between the

parties to allow it to survive longer unbroken.

So what of Behaviour description? I tend to think of categorizing the ways we've

attempted to model behaviour in Services in a few ways:

(1) Bind It. Our Service bindings have placeholders for operations that translate to a

Behaviour 'Action', whether it's the explicit SOAP Action or a combination of a few of

Page 2: A Service Oriented Design Pattern   Finite State Machine Behaviour

the service description bits. It is then left up to the toolkit on the platform of choice to

hook back up to a method call or invocation. If you see a method name called

'DoPurchaseOrderChecks()' you get the top-level understand of what the semantic

intent of the service action is. If the single parameter is a PurchaseOrder XML

message then it doesn't take Sherlock Holmes's Smarter Brother to deduct what

should go in and out. It's a lot like using a library that you didn't write, in that

documentation, specificity and experience all make up the rest of the 'contract'.

(2) Resource It. So much has been written about REST I'm almost loathed to add

that much. I think it's suffice to say that if you take a 'Resource' view of the Purchase

Order then you can reuse much of the webs infrastructure of a few simple HTTP

verbs, i.e. GET/PUT. You add context to what you want to do and which resource you

want to do it to but moving the description up into the endpoint, i.e. a

http://localhost/Acme/PurchaseOrders/ProcessQueue PUT on an XML body

containing a Purchase Order doesn't take Dr Watson to figure out either.

(3) Complicate It. Managing the cost of data and behaviour change between

systems is an entire IT industry sector called EAI. It is natural that the tools and

product vendors in this space want to commoditize this work and bring down the cost

of change. WebMethods, Biztalk etc all work around this concept. WS-BPEL is a Janus

like draft spec in that it covers a pretty wide remit in its 2 sections. You can see it as

either a 'coordination and sequencer' or 'process execution' depending on your

choice of lifestyle. It does represent the best attempt at modeling interactions

between services without 'just code', and the most charitable thing I can think of to

say is that it's not baked yet and might yet get somewhere good.

(4) Deploy It. The term Service Agent burnt magnesium bright for a while, similar to

MC Hammer's music career, although I see it used a lot less today. The idea of a

small chunk of Mediator pattern that is 'away from the Service' seems sensible and

can be generated to be a little more that '(1) Bind It' in terms that some limited

behaviour can live in the client behind the agent. Of course, the Achilles heel is that if

you want Services to be about interoperability and decentralized change

management then you've just shot yourself in the foot. A bit of a generalization, but

designs that tend to love deployed Service Agents tend to view SOD like 'The Son of

CORBA/DCOM' and have a fairly monoculture view of IT.

(5) Split It. I have now seen a couple of SOA descriptions that include 'Orchestration'

like Services, i.e. Services whose responsibility it is to make the Entity/Data Services

Page 3: A Service Oriented Design Pattern   Finite State Machine Behaviour

dance. You split your Domain Model by having Data-centric services and Behaviour-

centric services. Office Information Bridge loosely takes this approach of a

sequencing 'Actions' and I do feel this direction has some merit. It is a little similar to

'(3) Complicate It' in that you need someone else's run-time, but I can picture a lot of

the design concepts finding their way into PAG and the Enterprise Templates too. I

haven't seen much public feedback from Razorbill's as yet, and it might be the case

of 'So much to argue about, So little time' that stops us getting to 3rd Base of a

taxonomy together of different types of Service even?

Pattern Description

The following simple pattern is intended to offer another way to model limited

behaviour using Services.

The behaviour of a Service can be described by providing a 'finite state machine'

driven sequence of actions as part of the contract. The Data Contract of the Service

provides a number of 'anchor point' known states that can be considered part of the

structure of the document message. The client passes the XML message to the

Service and includes the element of the desired next state, say as part of the body.

The Service then processes this message and runs behaviour as part of the asked for

'state transition'. The Service can then accept the transition, hold it for further

processing or reject it.

Key concepts of the pattern:

- The Data Contract and a limited intent of the Behaviour are 'kept together' in a

single Service description. What a Purchase Order looks like and what it can do are

exposed together.

- The client not only knows the preferred structure of the data but also understands

the current available paths to get the 'domain object' to the next state in the FSM.

- The behaviour that can be described is limited to what you can model in a FSM for

that domain object, but it is (a) better than nothing, i.e. it is machine understandable

in terms of contract and (b) not exclusive, i.e. I am not proposing that this is the only

way you model your behaviour.

Page 4: A Service Oriented Design Pattern   Finite State Machine Behaviour

- It's a design pattern, in that it presumes you are designing and writing code rather

than relying on the middleware of some other existing infrastructure. The pattern

should be simple enough to code yourself as part of the existing Services

infrastructure you get from the technology platform vendors.

An analogy to this pattern is a 'Model View Controller' concept in presentation

architectures. Most user interfaces are driven by a finite state machine, in that the

sequence of steps can be codified into a Controller to (a) offer some flexibility for

change and (b) define enough separation as to make this change less intrusive: The

problem of coupling behaviour between Services is a similar one.

Worked Example

We have a Purchase Order (of course). A schema describes it as simply as possible.

The domain object behaviour can be modeled in the following way in terms of the

'lifecycle' of the data:

The Purchase Order schema codifies this state machine as a series of enumerations

of allowable states within the schema.

The 'Purchase Order' Service has the following set of operations:

msgPO  Create()

msgPO  Read( id )

Page 5: A Service Oriented Design Pattern   Finite State Machine Behaviour

msgPO  Update( msgPO )

bool   Delete( id )

msgPO  Import( msgPO )

The CRUD operation are self explanatory, but we now have an extra 'I' for the Import,

i.e. CRUDI. The Import method takes a single document of message type Purchase

Order. The 'Import' is less 'definite' than a 'Save' as it indicates the clients desire to

'do something' rather than an atomic operation guaranteed to go through.

The client indicates in the 'State' element of the Purchase Order that they want to

'Approve' this Purchase Order instance.

Presuming for this example that a 'Reviewed' Purchase Order already exists and can

be uniquely keyed upon, then the Service will run a series of 'pipeline' checks on the

requested state transition. Business rules will run based on what data is currently in

the PO, what PO has been passed and who has requested it.

What Works Well

The pattern works well for:

- Where you need to describe allowable behaviour to a 3rd party. As the behaviour is

often intrinsically linked with data structure, you get a versioning story that keeps

them consistent.

- You can Gateway a 'facade' very easily with this pattern, i.e. provide all your

business services through a common 'top level' Service interface that has a small

surface area, meaning small as in to protect, document and manage.

- Extra metadata included with the Purchase Order can help prepare the client for

what it needs to do, i.e. what fields are required and the like. This helps provide a

'coarse grained' interface very important for anything to do with XML Services.

- The pattern lends itself to Request/Response as well as Async Processing, as in the

limiting nature of the Import is what makes it self-contained.

What Doesn't Work As Well

Page 6: A Service Oriented Design Pattern   Finite State Machine Behaviour

- Some things don't lend themselves to being modeled with a FSM. That's ok, as the

pattern tends to get used like this:

PurchaseOrderService

 CRUDI

PurchaseOrderInteralService

 DoThis()               // Used by Import for A->B transition

 DoThat()               // Used by Import for B->C transition

 DoSomethingWeird()     // Exposed

 

PurchaseOrderDataService

 CRUD                   // Implements the top Service

...as in sometimes it is necessary to expose certain operations on the InternalService

too. The pattern lends itself to passing data messages around, rather than RPC

context-like instructions to go reformat harddisks, fiddle with configuration and the

like.

- You have to model upfront what the FSM will look like and sometimes that changes.

This is a fact of life and I tend to think of just like any other Data-centric schema

change. It is an important point that the FSM sequences are seen as 'anchor points'

from the Services perspective, i.e. if a 3rd party system receives a PO in 'Reviewed'

state and wants to do run all sorts of extra logic and states against it then that is fine

- as long as I receive it back in a state I understand. This is similar to the concept of

preserving data you don't understand, but from a behaviour point of view.

Anyway, this is probably far too long for a blog post so I should finish up. I just

wanted to throw the description out there sooner rather than later and I hope it is of

interest to some people.

It's also worth pointing out that this isn't a 'pattern first' exercise, in that I've been

working with a team of people doing this for about 3 years now. That isn't to say this

is a panacea or 'The Answer You Are Looking For' but I did want get across this isn't

Page 7: A Service Oriented Design Pattern   Finite State Machine Behaviour

all theory. Lot's of Services base software we have built is based around this design

pattern.

I hope this encourages more people to share their patterns and I welcome any

feedback: Unless it's negative, of course.