Tuesday 26 May 2009

Week 21 of 2009

First off, my week numbers seems to be off my one. This weekly report covers the previous two weeks which are actually week 20 and week 21 (not week 21/22). I can't go back and change the previous weekly report headings since I will break any cross references to those weekly reports.

I have been working on Action Language syntax and semantics, trying to nail down a sufficient but minimal Action Language for use in OOA09. I've been trying not to rush decisions here since I will have to live with these choices for the foreseeable future. One area in particular that I have been trying to nail down relates to wormholes and bridge mappings. To this end, I wrote a number of recursive design technical notes describing synchronous and asynchronous communications across bridges:

These notes took most of last week since they forced me to clarify a number of important issues, e.g. what happens when return coordinates and transfer vectors go out of scope.

I also realized that watchpoint mappings (object created mappings, object deleted mappings, object updated mappings, event generated mappings and operation invoked mappings) would not be sufficiently flexible. I would also need to allow reflexive bridges in certain situations. The problem here is the assumption that a watchpoint mapping involves two domains. It really involves one or more domains. Therefore, I am replacing watchpoint mappings with domain observers (object created observers, object deleted observers, object updated observers, event generated observers and operation invoked observers). These will be defined on domains rather than bridges but will have access to all domains used in the enclosing project. This will also eliminate the need for reflexive bridges.

Sunday 24 May 2009

Asynchronous Communications between Domains

This technical note should be read after Synchronous Communications between Domains since I have tried to avoid repeating myself too much here. Most asynchronous communications between domains involve:

  • request wormholes (domain-crossing events or bridging processes) in client domains,
  • control reception points (external events or synchronous services) in server domains,
  • and request mappings in bridges.
However, asynchronous communications may also involve:
  • solicit event parameters on request wormholes,
  • asynchronous return wormholes in server domains,
  • asynchronous return mappings in bridges,
  • and transfer vector types.

Request wormholes are associated with a terminator in a client domain and include domain-crossing events and bridging processes. A domain-crossing event may have any number of carried data items. A bridging process may have any number of user-defined input or output parameters. However, output parameters are not relevant here when dealing with asynchronous communications. Bridging processes are normally used for synchronous communication. However, they may also be used for asynchronous communication as long as a synchronous return mapping exists.

Control reception points are associated with a terminator in a server domain and include external events and synchronous services. External events indicate internal events (state model, domain-crossing or polymorphic events) that can arrive from outside a given domain via a specific terminator. Events may have any number of carried data items. Synchronous services may have any number of user-defined input or output parameters. However, output parameters are not relevant here when dealing with asynchronous communications. Unlike bridging processes, synchronous services may be used in a purely asynchronous manner since the results may not be required by a particular client domain. Dummy return coordinates are passed to synchronous services when they are invoked asynchronously allowing the server domain to execute a dummy synchronous return unaware that it has been invoked asynchronously.

A request mapping in a client-server bridge is implemented using an Action Language statement block. It maps a request wormhole to a control reception point. If the request wormhole is a domain-crossing event then the carried data items are passed as input parameters into the request mapping. Otherwise, the input parameters of the bridging process are passed into the request mapping. Request mappings have no output parameters. The code in a request mapping must either generate the associated external event or invoke the associated synchronous service. It may also decide to do neither without consequence. Output parameters should not be accessed when invoking a synchronous service asynchronously. Any attempt to do so is a static coding error. There may be any number of request mappings for a given request wormhole.

External events may be both unsolicited and solicited. Request mappings to external events define unsolicited events which either represent a new thread of control within the server domain or extend the existing thread of control associated with the client domain's request wormhole. Solicited events within a client domain on the other hand extend an existing thread of control associated with a previously invoked request wormhole to a server domain. Solicited events are defined using solicit event parameters on request wormholes. A request wormhole (whether used synchronously or asynchronously) may have zero to many solicit event parameters. A solicit event parameter holds a complete event instance created in a client domain which is then passed to a server domain as a transfer vector. The transfer vector can then be used to invoke an asynchronous return wormhole in the server domain which as a consequence generates a solicited event in the client domain.

[Wormhole96] proposed that transfer vectors should encapsulate partial event instances with all event data items determined from asynchronous return wormhole input parameters. OOA09 doesn't allow partial event instances at all. It does allow an event instance to be created from another event instance allowing new event data item values to be supplied. It also allows event data items to be read from an event instance in the same way as attributes can be read from an object instance. This allows full or partial overriding of event data items on event instances. However, this always involves creating a new event instance since event instances are immutable in OOA09.

Solicited event parameters have a multiplicity and conditionality providing some indication as to how many solicited events are expected by the client domain. If more than one solicited event is generated when no more than one was expected then an error should be reported but the solicited event is still generated. If no solicited events are generated but at least one was expected and all transfer vectors go out of scope then an error should be reported. A solicited event is not automatically generated here. This behaviour differs from what happens when all return coordinates go out of scope and a synchronous return hasn't been invoked. This is because a missing asynchronous return is a protocol error which should be handled in the appropriate state models while a missing synchronous return is a permanently blocked concurrent thread.

An asynchronous return wormhole is an abstract process associated with a terminator in a server domain which may be invoked in any composed operation (action or synchronous service). It may have any number of user-defined input parameters. Asynchronous return wormholes have no output parameters. A self parameter with a transfer vector type is also automatically defined. However, explicit asynchronous return wormholes are not always required in OOA09 since transfer vectors may arrive in a domain in a complete state allowing a solicited event to be immediately generated without involving an asynchronous return mapping.

An asynchronous return wormhole is normally invoked on a transfer vector value using an invoke return statement, e.g.

transfer_vector.return(message:"Hello World");
However, an implicit asynchronous return wormhole involving a complete transfer vector (one not associated with an asynchronous return wormhole) is always invoked using an ordinary generate statement, e.g.
generate transfer_vector;
The generate statement is used in this case since an asynchronous return mapping is never involved, i.e. the transfer vector's event instance is immediately generated (or delayed if a delay clause is used).

An asynchronous return mapping in a client-server bridge is implemented using an Action Language statement block. It maps an asynchronous return wormhole to a solicited event parameter. It is invoked whenever an asynchronous return is performed using a partial transfer vector. No asynchronous return mappings are required (or possible) for complete transfer vectors. The input parameters associated with a asynchronous return mapping match the input parameters of the asynchronous return wormhole. Asynchronous return mappings have no output parameters. A self parameter with an event instance type is also automatically defined. The self parameter contains the event instance wrapped by the asynchronous return wormhole's transfer vector. It can be used immediately to generate a solicited event. However, some adjustment will normally be required using the input parameters. Any adjustment will involve creating a new event instance. The code in an asynchronous return mapping will normally generate the associated external event. However, it is not required to do so. If there are no asynchronous return mappings for an explicit asynchronous return wormhole then the partial transfer vector is treated like a complete transfer vector, i.e. a solicited event is automatically generated from the transfer vector's wrapped event instance. However, this should be reported as an error. This behaviour differs from what happens when no synchronous return mapping is specified. If you don't want an asynchronous return then you shouldn't pass a transfer vector into a control reception point.

A predefined partial transfer vector type is defined for each asynchronous return wormhole allowing partial transfer vectors to be safely passed around within a domain since the parameters associated with a partial transfer vector can be statically determined within Action Language code. A single predefined complete transfer vector type is also defined allowing solicited events to be generated without the need for an explicit asynchronous return wormhole or an asynchronous return mapping. The predefined complete transfer vector type is generic. The predefined partial transfer vector types are partially generic in that they can be used across multiple control reception points.

Monday 18 May 2009

Synchronous Communications between Domains

All bridges between domains allow communications in both directions. Even though the domains being bridging are labelled as either client or server. Those roles may be reversed for a given communication. Explicit communications between domains are known as wormholes in Shlaer-Mellor OOA/RD. Wormholes were introduced in OOA96 and later defined in [Wormhole96] as an alternative to domain-crossing events and bridging processes. However, OOA09 integrates these concepts together to gain benefits from both approaches. All synchronous communications between domains involve:

  • bridging processes (request wormholes) in client domains,
  • synchronous services in server domains,
  • request mappings in bridges,
  • synchronous return wormholes in server domains,
  • synchronous return mappings in bridges,
  • and return coordinate types.

A bridging process is an abstract process associated with a terminator in a client domain which may be invoked in any composed operation (action or synchronous service). It may have any number of user-defined input and output parameters. A thread of control passes from one domain to another when a bridging process is invoked. A synchronous return must be invoked by a server domain to continue the original thread of control. Whether processing can still occur within the client domain while waiting for a synchronous return depends on how many concurrent threads have been allocated to the client domain.

A synchronous service (as defined in [SyncServ96]) is a composed operation implemented using an Action Language statement block or a process model. It is associated with a terminator in a server domain. It may have any number of user-defined input and output parameters. A special Return Coordinate parameter is also defined automatically. This parameter is required to invoke a synchronous return wormhole. Return coordinates can be passed on within the server domain as event data items or ordinary parameters and stored as attributes. However, they should not be stored for long since the client domain is waiting for a result. They can also be passed to other domains as external values. However, they can't be used to invoke synchronous returns in other domains.

A request mapping in a client-server bridge is implemented using an Action Language statement block. It maps a request wormhole (domain-crossing event or bridging process) to a control reception point (external event or synchronous service). A synchronous communication always requires a bridging process and a synchronous service. If a domain-crossing event is mapped to a synchronous service then any synchronous returns will be ignored. If a bridging process is mapped to an external event then no synchronous return is possible since new return coordinates are not passed to external events. However, it is still possible to carry an existing return coordinate via an event. The input parameters associated with a request mapping match the input parameters associated with the bridging process. Request mappings have no output parameters. The code in a request mapping must invoke the synchronous service converting bridging process input parameters to synchronous service input parameters.

There may be any number of request mappings for a given bridging process. However, only one synchronous return can be used to satisfy a given invocation. OOA09 allows multiple request mappings, all of which may invoke a synchronous return. Only the first response will be used to satisfy the request. Any additional responses will be ignored. Whether it is good design practice to allow multiple responses here is open to debate. If all return coordinates associated with the synchronous services invoked in response to a bridging request go out of scope then the bridging process invocation can terminate. If all output parameters associated with the bridging process are conditional or have default values then this is a recoverable error that should be flagged but is otherwise acceptable. If there are any mandatory output parameters without default values then this is a fatal error with serious consequences since the original thread of control can't continue. All such fatal errors can be eliminated from deployed systems by ensuring that all bridging process output parameters are either conditional or have a default value. A software architecture may place time limits or other restrictions on bridging processes as long as a default synchronous return is possible, e.g. a software architecture may break a deadlock by invoking default synchronous returns on deadlocked synchronous communications.

A synchronous return wormhole is an abstract process associated with a synchronous service (and as a consequence a terminator) in a server domain which may be invoked in any composed operation (action or synchronous service). The input parameters are automatically determined from the output parameters of the associated synchronous service. Synchronous return wormholes have no output parameters. A self parameter with a return coordinate type is also automatically defined. However, explicit synchronous return wormholes are not actually required in OOA09 since synchronous return mappings and return coordinate types are associated directly with synchronous services rather than synchronous return wormholes. The only benefit of an explicit synchronous return wormhole is that it can be labelled and shown separately on process models.

A synchronous return wormhole is normally invoked on a return coordinate value using an invoke return statement, e.g.

return_coordinate.return(message:"Hello World");
However, within a synchronous service statement block, a synchronous return wormhole can also be invoked using an ordinary non-empty return statement, e.g.
return message:"Hello World";
An empty return statement can't be used for this purpose even if there are no output parameters.

A synchronous return mapping in a client-server bridge is implemented using an Action Language statement block. It maps a synchronous service to a bridging process. It is invoked whenever an explicit or implicit synchronous return occurs. The input parameters associated with a synchronous return mapping match the output parameters of the synchronous service while the output parameters match the output parameters of the bridging process. The code in a synchronous return mapping must convert the synchronous service output values to bridging process output values. If there are no synchronous return mappings for a synchronous service then any synchronous returns will simply be ignored.

A predefined return coordinate type is defined for each synchronous service allowing return coordinates to be safely passed around within a domain since the parameters associated with a return coordinate can be statically determined within Action Language code. There is no generic return coordinate type in OOA09 as a consequence. However, that does not mean that return coordinates can't be passed to a service domain as external values since any return coordinates must be passed back to their server domains (requiring type verification) before they can be used.

Monday 11 May 2009

Week 19/20 of 2009

I didn't have much to report last week since I was mostly doing behind the scenes coding for OOA Tool. This week I returned to the Action Language. The first step was to revisit the syntax grammar for OAL since I want the Action Language for OOA09 to be backwards compatible where possible. The second step was to update the syntax grammar for the OOA09 Action Language. The third step is to update the overview documentation which hasn't been uploaded yet. Later steps include updating the parser in OOA Tool, implementing an interpreter and debugging interface, and updating the Action Language Subsystem for the OOA of OOA. Only the first two steps will be discussed here. The general overview should be uploaded in the coming week and the other work will completed later.

There are three documents that define the Object Action Language (OAL) from Mentor Graphics:

  • BPAL97 which defines the Action Language in BridgePoint 4.2,
  • OAL02 for later versions of BridgePoint,
  • and OAL08 for the latest version of BridgePoint UML Suite.
OAL has undergone very few changes over the last 10 years. One could say the same for the Action Specification Language (ASL) from Kennedy Carter. However, As I have said before, I prefer the simplicity of OAL. I updated the OAL syntax grammar in the BridgePoint 4.2 Model to handle BPAL97, OAL02 and aspects of OAL08 with other aspects mentioned in embedded comments. The only aspect of OAL08 which has not been captured is the new send statement relating to components and interfaces. The OAL syntax grammar is given below:
Syntax and Lexical Rules for Action Language

The OOA09 Action Language is currently captured as part of the OOA Tool Model. However, it will shortly be put under change control in the same way as the OOA of OOA and OOA Interchange Format are under change control. The OOA09 syntax grammar is given below:

Syntax and Lexical Rules for Action Language

OOA09 adds a small number of new statements:

  • a declare statement,
  • a switch control structure statement,
  • a reclassify object instance statement,
  • and a delete event instance statement.
There are numerous other changes but I will only discuss the new statements above today. The other changes will be discussed in detail in the Action Language overview which should get uploaded in the coming week.

The declare statement allows stronger and weaker type checking. Variables can still be implicitly declared using assignment statements etc. However, users can now declare variables explicitly using predefined types or user defined types from their model. New data types can't be (and don't need to be) defined within Action Language code. All implicit variable declarations can now be replaced with explicit declarations if needed. The declare statement also allows transient non-object instance sequences and sets to be specified since multiplicity is associated with data items (e.g. variables) in OOA09.

The switch statement allows enumerated types to be used safely (including current_subtype and current_state information) since all legal values must be handled as cases. If new legal values are added or old ones are removed then all associated switch statements will need to be updated. Java and C++ switch statements cover up errors far too easily.

The reclassify object instance statement enables users to drop explicit creation and deletion of non-leaf object instances and subtype-supertype relationships. Non-leaf object instance creation will be disabled by default in OOA Tool. However, for backwards compatibility with OAL, users will be able to create non-leaf object instances but if they do so they will need to create all non-leaf object instances and will need to relate and unrelate all subtype-supertype relationships.

The delete event instance statement is part of the delayed event support added to OOA09. Event instances can be created and stored and later turned into generated event instances which may be given a delay when generated. Rather than add the cancel statement (specified in xtUML02) which only cancels a single generated event instance. OOA09 cancels all generated but delayed event instances associated with a specific event instance when it is explicitly deleted. However, OOA Tool will also support the complete Timer interface defined in BridgePoint for backwards compatibility.

On a final note, I came across the ModelDriven.org Portal which includes a downloadable Foundational UML (fUML) Reference Implementation. Like OOA Tool, it's written in Java and requires Java SE 6 or later. I haven't explored it yet.