ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
π-ARL: An Architecture Refinement Language for Formally Modelling the Stepwise Refinement of Software Architectures Flavio Oquendo University of Savoie at Annecy ESIA – B.P. 806 – 74016 Annecy Cedex – France
[email protected] Abstract A key aspect of the formal development of any software system is the specification and stepwise refinement of its architecture. In a stepwise refinement, a sequence of steps starting from an abstract specification of the architecture leads to a concrete, implementation-centred, architectural model. Each refinement step typically leads to a more detailed architecture description that increases the determinism while implying properties of the abstract specification. Enabling stepwise architecture refinement is a new challenge for the formal development of complex software systems. This article describes π-ARL, a novel Architecture Refinement Language (ARL) that has been designed in the ArchWare European Project to address formal refinement of software architectures. It is a formal, well-founded theoretically language based on a rewriting logic. Its underlying approach for architecture refinement is underspecification, i.e. at a high-level of abstraction, when specifying an architectural element, certain aspects can be left open. The decrease of this underspecification establishes behaviour but also port, structure, and data refinement relations. The underlying foundation for architected behaviours is the higher order typed πcalculus. π-ARL focuses on formally modelling the stepwise refinement of software architectures through a set of architecture refinement primitives. Keywords: Architecture Refinement Languages, Stepwise Refinement, Software Architectures, Formal Development Techniques
that may differ with respect to diverse aspects. For instance, an abstract architecture containing functional components related by data flow connections may be implemented in a concrete architecture in terms of procedures, control connections, and shared variables. In general, an abstract architecture is smaller and easier to understand; a concrete architecture reflects more implementation concerns. Vertical refinement steps add more and more details to abstract models until the concrete architectural model is described. A refinement step typically leads to a more detailed architectural model that increases the determinism while implying properties of the abstract model. Thus, an abstract – platform independent – architecture description can be refined to a concrete – platform specific – architecture description following a Model-Driven Architecture [8]. Figure 1 depicts the overall approach of describing and refining architecture descriptions [32].
describe architecture application architect architecture description
refine architecture
refinement of
1. Introduction generated from Software architecture has emerged as an important subdiscipline of software engineering. A key aspect of the formal development application of any software system is the specification and stepwise refinement of its architecture, i.e. the fundamental organisation of the system embodied in its components, their relationships to each Figure 1. Architectural refinement other, and to the environment, and the principles guiding its design Refinement is the formal relation that relates two different models, and evolution [17]. an abstract and a more refined. Hereafter, it is noted ►: Indeed, complex systems cannot be architected in one step. In a abstractModel ► refinedModel stepwise refinement, a sequence of steps starting from an abstract specification of the architecture leads to a concrete, implementaRefinement relations are reflexive and transitive: tion-centred, architectural model. These refinement steps can be carried out along two directions: “horizontal” and “vertical”. abstractModel ► refinedModel1 ► refinedModel2 ► … Horizontal refinement is concerned by applying different refine► concreteModel ment actions at different parts of the same abstract architecture. Thus, a concrete model is a refinement of an abstract model via For instance, by partitionning an abstract component in its parts at intermediate steps: the same abstraction level. abstractModel ► concreteModel The concrete architecture of a software system is often developed through a vertical hierarchy of related architectures. An architec- An architecture concrete model can be thought of as just another ture hierarchy is a linear sequence of two or more architectures architectural model in a style suitable for implementation. 1
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
This article describes the π-Architecture Refinement Language (π- picts its main constituents3. ARL) [28] that enables the formal stepwise refinement of software architectures modelled with π-ADL [29][31], as depicted in Figure 2. Applying an architecture refinement action expressed in π-ARL on an “abstract” architecture description expressed in π-ADL yields a “more concrete” architecture description also expressed in π-ADL.
abstract architecture description in π-ADL
architecture refinement action in π-ARL
Figure 3. Architectural concepts in π-ADL result: more concrete architecture description in π-ADL
Components are described in terms of external ports and an internal behaviour. Their architectural role is to specify computational elements of a software system. The focus is on computation to deliver system functionalities.
Ports are described in terms of connections between a component and its environment. Their architectural role is to put together π-ARL is a novel formal refinement language that has been de- connections providing an interface between the component and its environment. Protocols may be enforced by ports and among signed in the ArchWare1 European Project: ports. • it is a formal, well-founded theoretically language for refining architectures whose architected behaviours are based on the Connections are basic interaction points. Their architectural role is π-calculus [23][9][10] or the higher-order typed π-calculus to provide communication channels between two architectural elements. Connections may be unified to enable communication. [35][36]; • it is automated by tools, i.e. a refinement toolset [22] provid- A component can send or receive values via connections. They ing support for automated model-driven refinements. can be declared as output connections (values can only be sent), The remainder of this article is organised as follows. Section 2 input connections (values can only be received), or input-output introduces key concepts and constructs for describing architec- connections (values can be sent or received). tures in π-ADL. Section 3 presents the different forms of refine- Connectors are special-purpose components. They are described ment relation in π-ARL. Section 4 describes the π-ARL as components in terms of external ports and an internal behavrefinement primitives and the π-ARL syntax. In order to illustrate iour. However, their architectural role is to connect together comthe use of π-ARL, section 5 briefly presents a case study on the ponents. They specify interactions among components. stepwise refinement of an abstract architecture of a data acquisiTherefore, components provide the locus of computation, while tion system. Then in section 6 we compare π-ARL with related connectors manage interaction among components. A component work. To conclude, in section 7, we briefly outline the π-ARL cannot be directly connected to another component. In order to toolset for supporting stepwise architecture refinement. have actual communication between two components, there must be a connector between them. 2. Architecture Description Both components and connectors comprise ports and behaviour. In 2.1 Concepts order to attach a port of a component to a port of a connector, at π-ADL2 supports description of software architectures from a run- least a connection of the former port must be attached with a contime perspective. In π-ADL, an architecture is described in terms nection of the later port. A connection provided by a port of a of components, connectors, and their composition. Figure 3 de- component is attached to a connection provided by a port of a connector by unification or value passing. Thereby, attached connections can transport values (that can be data, connections, or 1 The ArchWare European Project is partially funded by the even architectural elements). Commission of the European Union under contract No. IST2001-32360 in the IST-V Framework Program. 2 A concise description of π-ADL illustrated with case studies 3 The UML Profile for π-ADL [3] is used for presenting diacan be found in [29]. grammatic models. 2 Figure 2. Architectural refinement with π-ARL
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
From a black-box perspective, only ports (with their connections) • of components and connectors and values passing through connections are observable. From a white-box perspective, internal be- • haviours are also observable.
portDeclarations is the set of port declarations in the scope of archDefId used for grouping connections, compositionOfComponentsUsingConnectors is the architected set of architectural elements of archDefId (these elements interact via connections of ports). Architectural elements can be components and connectors that may themselves be described by architectures, property must hold to guarantee the correctness of the architecture description.
Components and connectors can be composed to construct composite elements (see Figure 4), which may themselves be components or connectors. Composite elements can be decomposed and recomposed in different ways or with different components in • order to construct different compositions. Composite components and connectors comprise external ports A port is declared in terms of incoming and outgoing connections: (i.e. observable from the outside) and a composition of internal architectural elements. These external ports receive values coming from either side, incoming or outgoing, and simply relay it to the other side keeping the mode of the connection. Ports can also be declared to be restricted. In that case, constituents of composite elements can use connections of restricted ports to interact with one another but not with external elements.
port portDefId is { inConnectionDeclarations outConnectionDeclarations inoutConnectionDeclarations } assuming { portProtocol } where: • •
• •
inConnections is the set of connections of portDefId used only for input, outConnections is the set of connections of portDefId used only for output, inoutConnections is the set of connections of portDefId used for both input and output, portProtocol expresses the port protocol on the set of connections.
A connection is declared as follows, where the mode is in, out or inout and ValueType is the type of values that can be passed Architectures are composite elements representing systems. An though the declared connection. architecture can itself be a composite component in another architecture, i.e. a sub-architecture. connection connectionId is mode ( ValueType ) Figure 4. Architectural composition in π-ADL
2.2 Constructs π-ADL provides primitive constructs for supporting the description of all these architectural concepts. In π-ADL, architectures, components, and connectors are formally specified in terms of typed abstractions over behaviours. Architectures are described as follows4: architecture archDefId is abstraction ( typedParameters ) { typeDeclarations valueDeclarations portDeclarations behaviour is { compositionOfComponentsUsingConnectors} } assuming { property }
π-ADL is formally defined by a formal transition and type system. The π-ADL abstract syntax is completely defined in [31]. Its concrete textual syntax (with a tutorial) is presented in [27]. 3. Architecture Refinement Relation Software applications are usually developed in several steps. Indeed, the concrete architecture of a software system is often developed through vertical and horizontal refinements of related architectures that differ respectively with respect to abstraction and partition dimensions.
π-ARL supports both vertical and horizontal refinement. In πARL, the underlying approach for architectural refinement is underspecification, i.e. at a high-level of abstraction, when specifywhere: ing an architectural element, certain aspects can be left open. The decrease of this underspecification establishes a refinement rela• archDefId is a unique architecture definition identifier, • typeDeclarations is the set of explicit type declarations intro- tion for architectural elements. ducing new type aliases in the scope of archDefId, they may The refinement relation in π-ARL, from an external or internal be used in the declaration of values, ports, and behaviour, point of view, comprises four forms of refinement: • valueDeclarations is the set of explicit value declarations, • behaviour refinement, • port refinement, 4 • structure refinement, Language keywords are written with bold. 3
ACM Software Engineering Notes •
Volume 29, Issue 5 (September 2004)
finement compositions in both vertical and horizontal dimensions, from external or internal points of view. When applied, they refine In behaviour refinement, the underspecification may concern the architectural models described in π-ADL outputting new refined external (observable) behaviour or the internal behaviour of an architectural models also in π-ADL. architectural element. The external behaviour of an architectural element is the behaviour that its environment can observe, i.e. its 3.1 Behaviour Refinement behaviour from an external point of view. The internal behaviour concerns the internal expression of behaviour within the scope of An architectural model is a behaviour refinement of another given the architectural element. The ports of an architectural element model if all the behaviour properties of the latter are implied by provide the interaction points (i.e. connections) between the ele- the behaviour properties of the former. Behaviour properties are ment and its environment, i.e. its ports from an external point of defined by behaviour expressions in π-ARL. view. The structure of an architectural element is its internal struc- Behaviour refinement relates architectural models of the same set ture in terms of sub-architectural elements and their connected of ports. The refined (more concrete) model may impose a more ports, i.e. the structure within the scope of the architectural ele- constrained behaviour and properties than those imposed by the ment from an internal point of view. Data refinement is concerned given (more abstract) model. with the refinement of data structures. To verify that a development step is a behaviour refinement it is The most fundamental notion of refinement in π-ARL is behaviour sufficient to verify that the behaviour expression of the refined refinement. The other forms of refinement imply behaviour re- model implies the one of the given abstract model. That is, all posfinement modulo port, structure and data mappings. sible behaviours of the refined model are also possible behaviours In general, architectural refinement is a combination of the four of the abstract model. The refined model should be more determiforms of refinement. For instance, an architect can define an ab- nistic than the abstract one. In the case of external behaviour restract architecture, then “data” refine that architecture in order to finement, the implication relates observable behaviours; in the introduce base and constructed data types, then “port” refine the case of internal behaviour refinement, the implication relates all architecture to have ports with finer grain connections carrying (observable and restricted) behaviours. data of different types, then “structure” refine its composite behav- To express these concerns, the refinement relation is specialised as iour by adding new finer grain connectors, and so on. follows, where [b] denotes external behaviour refinement and ]b[ data refinement.
π-ARL provides constructs for defining refinements of the four internal behaviour refinement: forms cited so far, according to external or internal points of view. abstractModel [b]► refinedModel Composite refinements can be defined in terms of refinement abstractModel ]b[► refinedModel primitives and composite refinements themselves. Refinement primitives comprise: 3.2 Port Refinement • adding, removing, replacing, or transforming type or value An architectural model is a port refinement of another given model if it is a behaviour refinement modulo the mapping of ports declarations of an architecture, • adding, removing, replacing, or transforming ports of an ar- between the two models. These mappings are defined in π-ARL. chitecture, Port refinement relates architectural models of different sets of • adding, removing, replacing, or transforming components or ports (thereby it may relate different sets of connections). The connectors in an architecture, or transforming the behaviour refined (more concrete) model may impose more constrained proof an architecture, or the behaviour of a component or contocols and properties than those imposed by the given (more abnector in an architecture, stract) model. • exploding and imploding components or connectors in an architecture, or unifying and separating connections in an ar- To verify that a development step is a port refinement it is sufficient to verify that the behaviour expression of the refined model chitecture, or unifying and separating connection relays5. implies the one of the given abstract model modulo the port mapThese primitives, applied step by step, allow the incremental trans- pings. That is, all possible behaviours of the refined model modulo formation of an architecture description. These transformations are the port mappings are also possible behaviours of the abstract enforced to be refinements if preconditions of refinement primi- model. tives are satisfied and proof obligations discarded. A refinement engine based on rewriting logics runs the refinement descriptions To express these concerns, the refinement relation is specialised as expressed in π-ARL generating further refined architectures. Code follows, where [p] denotes port refinement (port refinement is always an external refinement): is generated from refined (concrete) architectures. The π-ARL is a formal (executable) refinement language providing architecture-centric refinement primitives and supporting re5
abstractModel [p]► refinedModel
3.3 Structure Refinement Besides connecting component instances together, the architec- An architectural model is a structure refinement of another given ture must express the binding between external ports and ports model if it is a behaviour refinement modulo the mapping of architectural structures between the two models. These mappings are of components. This binding is expressed by connection relay. 4
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) •
defined in π-ARL.
Structure refinement relates architectural models of the same set of • ports. The refined (more concrete) model may impose a more constrained behaviour and more constrained properties than those imposed by the given (more abstract) model.
adding, removing, replacing, or transforming ports of an architecture, adding, removing, replacing, or transforming components or connectors in an architecture, or transforming the behaviour of an architecture, or the behaviour of a component or connector in an architecture, exploding and imploding components or connectors in an architecture, or unifying and separating connections in an architecture, or unifying and separating connection relays6.
To verify that a development step is a structure refinement it is • sufficient to verify that the behaviour expression of the refined model implies the one of the given abstract model modulo the structure mappings. That is, all possible behaviours of the refined model modulo the structure mappings are also possible behaviours These basic actions, applied step by step, allow to incrementally refine an architecture abstraction. of the abstract model. To express these concerns, the refinement relation is specialised as In order to apply refinement actions, the following notation is follows, where ]s[ denotes structure refinement (structure refine- used: ment is always an internal refinement):
architecture archRefId refines archDefId using { applicationsOfRefinementActions } assuming { properties }
abstractModel ]s[► refinedModel
3.4 Data Refinement An architectural model is a data refinement of another given A similar notation is used for refining components and connectors model if it is a behaviour refinement modulo the mapping of data within an architecture. structures and types between the two models. These mappings are defined in π-ARL. 4.1 Deferring an Architecture Description Data refinement relates architectural models of the same set of An undefined architecture, i.e. an architecture that is completely ports. The refined (more concrete) model may impose more con- unspecified (no type declarations, no ports, no behaviour) can be strained behaviour and properties than those imposed by the given expressed as follows. (more abstract) model. architecture archDefId is abstraction { To verify that a development step is a data refinement it is suffibehaviour is { deferred } cient to verify that the behaviour expression of the refined model } implies the one of the given abstract model modulo the data mappings. That is, all possible behaviours of the refined model modulo the data mappings are also possible behaviours of the abstract 4.2 Primitives for Adding, Removing, Replacing, and model. Transforming Type and Value Declarations To express these concerns, the refinement relation is specialised as Type declarations can be added to an architecture if the type follows, where [d] denotes external data refinement and ]d[ inter- names introduced are fresh names in the architecture. nal data refinement: architecture archRefId refines archDefId abstractModel [d]► refinedModel using { types includes t } abstractModel ]d[► refinedModel External data refinement is related to data refinement within ports. Introducing new type declarations does not change the behaviour Internal data refinement is related to data refinement within the of the architecture. internal scope of the architectural element. Type declarations of an architecture can be removed if they are not used in the behaviour of the architecture. Thereby, the behaviour 4. Architecture Refinement Primitives An architecture refinement can be carried out by steps. A basic of the architecture is not modified. step is defined in terms of refinement primitives that can transform an architecture. This section describes the refinement primitives provided by π-ARL and the syntax for their application in a stepwise architecture refinement.
architecture archRefId refines archDefId using { types excludes t }
As mentioned so far, primitives for refining architectures provide Type declarations of an architecture can be replaced if the type names introduced are fresh names. Replacing type declarations features for: •
adding, removing, replacing, or transforming type or value declarations of an architecture,
6
5
Besides connecting component instances together, the architecture must express the binding between external ports and ports of components. This binding is expressed by connection relay.
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
does not change the behaviour of the architecture as types replaced of a replaced port, including connection names, must be a subset of the new one. Replacement is expressed as follows. must by equivalent. architecture archRefId refines archDefId using { types replaces t by rt }
architecture archRefId refines archDefId using { ports replaces p by rp }
The behaviour of the architecture is not modified as an existing The behaviour of the architecture is not modified as an existing type is replaced by an equivalent type. Semantically, it is equiva- port is replaced by an equivalent port. Semantically, it is equivalent of type renaming. lent of renaming plus adding new non-used connections. Type declarations can be transformed. These transformations must Ports of architectures can be transformed. These transformations preserve all properties of the more abstract architecture. must preserve all properties of the more abstract architecture. architecture archRefId refines archDefId using { types where { t0, …, tn } becomes { rt0, …, rtn } }
architecture archRefId refines archDefId using { ports where { p } becomes { rp }
Mapping (downward/upward) functions should be defined in or- Mapping (downward/upward) functions should be defined in order to enable verification of properties. der to enable verification of properties. architecture archRefId refines archDefId using { types where { t0, …, tn } becomes { rt0, …, rtn } assuming { mapping mapk(rti…rtj)=tk } }
architecture archRefId refines archDefId using { ports where { p } becomes { rp } assuming { mapping mapk(rpi…rpj)=pk } }
In a similar way, values can be added, removed, replaced, and In addition to manipulating ports, refinement primitives are protransformed. vided for adding, removing, replacing, and transforming connections of an architecture. 4.3 Primitives for Adding, Removing, Replacing, and A connection can be added as a new input, output, or input-output Transforming Ports and Connections in Ports connection to a port of an architecture if it is a connection with a A port can be added as a new port to an architecture if it is a port fresh name in the port of the architecture. with a fresh name in the architecture: architecture archRefId refines archDefId using { connections includes p::c }
architecture archRefId refines archDefId { using { ports includes p }
The behaviour of the architecture is not modified as the connecThe behaviour of the architecture is not modified as the new port tion is a fresh connection not used in the behaviour of the architechas a fresh name not used in the behaviour of the architecture. ture. A port of an architecture can be removed if it is not used in the An input, output, or input-output connection of an architecture can behaviour of the architecture. Thereby, the behaviour of the archi- be removed if it is not used in the behaviour of the architecture. tecture is not modified as the port is not used in its behaviour. Thereby, the behaviour of the architecture is not modified as the connection is not used in its behaviour. architecture archRefId refines archDefId using { ports excludes p } architecture archRefId refines archDefId using { connections excludes p::c } Adding and removing ports are complementary operations. They preserve the behaviour of the architecture as it is not modified. Adding and removing input, output, or input-output connections The following actions on connections allow managing connections are complementary operations. They preserve the behaviour of the in the scope of ports in architectures. architecture as it is not modified. Ports of an architecture can be replaced. A port can be replaced by The actions for adding and removing input, output, or input-output a new one if the new port is type equivalent to the one to be re- connections of ports are basic actions to perform incremental replaced and it has a fresh name. Replacing a port is equivalent to finements of architectures, for instance, first adding a new output verifying type equivalence, removing the existing port and adding connection to an architecture than refining its behaviour to use that the new one in an atomic manner. It is worth noting that the port is new connection to provide a more constrained output. also replaced in the behaviour expression. The set of connections 6
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
Input, output, or input-output connections of an architecture can components of the architecture or with connections of the archibe replaced. A connection can be replaced by a new one if the new tecture itself. connection is type equivalent to the one to be replaced and it has a fresh name. Replacing a connection is equivalent to verifying type architecture archRefId refines archDefId equivalence, removing the existing connection and adding the new using { components excludes c } one in an atomic manner. It is worth noting that the connection is also replaced in the behaviour expression. Adding and removing components are complementary operations. They preserve the behaviour of the architecture as the component architecture archRefId refines archDefId added or removed is not connected. using { connections replaces p::c by p::rc } A component can be replaced in an architecture without changing its behaviour if it has no unified connections with connections of The behaviour of the architecture is not modified as an existing other components of the architecture or with connections of the connection is replaced by an equivalent connection. Semantically, architecture itself. it is equivalent of renaming. By syntactic convention, if there is only one port in the architecture, the port name is optional in designating connections. Also by syntactic convention, if no port is explicitly created in an architecture there is an anonymous port implicitly created.
architecture archRefId refines archDefId using { components replaces c by rc }
The behaviour of the architecture is not modified as the replaced Connections can be transformed. These transformations must pre- component is not in interaction with other components of the arserve all properties of the more abstract architecture. Designation chitecture or the architecture environment. of connections may need designation of ports. Using the previous actions, an architect can describe an architecture in a hierarchical way, i.e. describing architectures where architecture archRefId refines archDefId components and even connectors can themselves be described as using { connections where { c } becomes { rc } architectures. An atomic component can be replaced by a composite one, i.e. by an architecture, using the replace action. Mapping (downward/upward) functions should be defined in orOnce an architecture is described, an architect can explode a comder to enable verification of properties. ponent that is itself described by an architecture. architecture archRefId refines archDefId using { connections where { c } becomes { rc } assuming { mapping mapk(rci…rcj)=ck } }
architecture archRefId refines archDefId using { components explodes c } The explosion of a composite component c in an architecture a produces a new architecture where all components and connectors of c are included in the architecture a but c itself is excluded.
4.4 Primitives for Adding, Removing, Replacing, and Transforming Components and Connectors A component can be added to an architecture without changing its behaviour if it has no unified connections with connections of connectors of the architecture or with connections of the architecture itself.
It is worth noting that this action changes the scope of components and connectors as components and connectors of c become components and connectors of a. In order to avoid that the behaviour of a changes, all restricted names of c must be different from names of a. If needed a renaming can be carried out using the following clause: where { newName renames currentName }.
architecture archRefId refines archDefId using { components includes c }
The complementary action of the explosion of a component is the implosion of a set of components and connectors as a subThe behaviour of the architecture is not modified as the added architecture. The sub-architecture is embodied as a new compocomponent is not in interaction with other components of the ar- nent. chitecture or the architecture environment. architecture archRefId refines archDefId For instance, in order to refine an architecture, one can add a new using { components implodes { sc } as rc } component without connections, then can add input and output connections, and then refine the behaviour of the added compoThe implosion of a set of components and connectors as a subnent. architecture produces a new composite component with a behavIn an equivalent way, components can be removed: a component iour that is given by the composition of the set of components and can be removed from an architecture without changing its behav- connectors. The components and connectors that have been imiour if it has no unified connections with connections of other ploded are excluded of the architecture and become components 7
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
and connectors of the sub-architecture, i.e. of the composite com- Separation is expressed as follows. ponent. architecture archRefId refines archDefId In a similar way, connectors can be added, removed, replaced, and using { connections separates cs::p::oc from cd::q::ic } transformed. The behaviour of the modified architecture must be a refinement of the behaviour of the architecture before modification.
4.5 Primitives for Transforming the Behaviour of an Architecture or its Component and Connectors An architecture can be refined by transforming its behaviour.
Besides connecting components together through connectors, the architecture can express the binding between external ports and architecture archRefId refines archDefId ports of components by connection relay. A free connection in an using { behaviour becomes rb } external port can be relayed to or from another free one in an internal port if they are type equivalent and have the same outIn some cases, in order to verify that the new behaviour is a re- put/input mode. finement of the abstract behaviour some assumptions on the values Connection relay is expressed as follows. received via free input connections are needed. Then the refinement primitive is used with assumption. architecture archRefId refines archDefId using { connections relays a::ep::ec with c::ip::ic } architecture archRefId refines archDefId using { behaviour becomes rb Separation is expressed as follows. assuming { -- assumption on free input connections } } architecture archRefId refines archDefId using { connections separates ep::ec from c::ip::ic } Behavioural refinement of an architecture usually leads to true behavioural refinement. The behaviour of the modified architecture must be a refinement An architecture can be refined by transforming the behaviour of its of the behaviour of the architecture before modification. components. 4.7 Syntax for Defining and Applying Refinement Primitives
architecture archRefId refines archDefId using { c::behaviour becomes rb }
π-ARL provides constructs for describing architectures and their refinements. The concrete syntax of π-ARL is defined in terms of a context free grammar expressed in an extended version of In some cases, in order to verify that the new behaviour is a re- Backus-Naur Form. The context free grammar is specified by a set finement of the abstract behaviour of the component some as- of production rules. Each production rule specifies the manner in sumptions on the values received via free input connections are which a particular syntactic category can be formed. Syntactic needed. Then the refinement action is used with assumptions. categories have names which are used in productions and are distinguished from names and reserved words in the language. The syntactic categories can be mixed in productions with terminal architecture archRefId refines archDefId symbols which are actual symbols of the language itself. Thus, by using { c::behaviour becomes rb following the productions until terminal symbols are reached, the assuming { -- assumption on free input connections } set of legal declarations can be derived. } The concrete syntax of the π-ARL is defined using the following In a similar way, an architecture can be refined by transforming meta-notation for the concrete production rules: the behaviour of its connectors. • keywords are written with bold, 4.6 Primitives for Unifying and Separating Connections in an • non-terminals are written without bold, • optional parts are written in square brackets [], Architecture • a sequence of zero, one or more elements is written using []*, Output and input connections of components and connectors of an architecture can be unified. A connection can be unified with an- • alternative choices are written separated by |. other one if they are type equivalent and have complementary out- Comments are enclosed by --. put/input modes. id ::= letter [ letter | digit | _ ]* Unification is expressed as follows. scopedId ::= id [ ::scopedId ] architecture archRefId refines archDefId using { connections unifies cs::p::oc with cd::q::ic }
indicates that an identifier can be formed as a letter, optionally followed by zero or many letters, digits or underscores and that a 8
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
scoped identifier is formed by an identifier followed by :: and a Refinement actions comprise actions for refining data, port, behaviour, and structure. scoped identifier, recursively defined. A refinement expression is defined by an architectural abstraction Data refinement is defined in terms of transformations on types or a refinement definition or a refinement application followed by and values as depicted in Figure 8. a refinement expression as shown in Figure 5. typeAction ::= includes typeDec refinementExp ::= ( architecturalAbstraction | refinementDef | refinementApp ) [ . refinementExp ]
| excludes scopedId | replaces scopedId by typeDec | where { scopedId [ , scopedId ]* } becomes { typeDec [ , typeDec ]* }
Figure 5. Architectural refinement expression
[ assuming { property } ]
Architecture descriptions are specified by architectural abstractions expressed using π-ADL as defined in Figure 6.
valueAction ::= includes valueDec | excludes scopedId
architecturalAbstraction ::= archtype id is abstraction archtype ::=
architecture | component | connector
abstraction ::=
abstraction [ ( id : ValueType [ , id : ValueType ]* ) ] {
| replaces scopedId by valueDec | where { scopedId [ , scopedId ]* } becomes { valueDec [ , valueDec ]* } [ assuming { property } ]
[ typeDec [ . typeDec ] * . ] [ valueDec [ . valueDec ] * . ] [ portDec [ . portDec ] * . ]
Figure 8. Syntax for applying data refinement
behaviour is { behaviour }
Port refinement is defined in terms of transformations on ports and connections as depicted in Figure 9.
} assuming { property } typeDec ::=
type name is ValueType
valueDec ::=
value name is expression
portDec ::=
port name is restriction {
portAction ::= includes portDec | excludes scopedId
[ connectionDec [ . connectionDec ] * ]
| replaces scopedId by portDec
} assuming { protocol is property } restriction ::=
free | restricted
connection ::=
connection name is mode ( ValueType )
mode ::=
in | out | inout
| where { scopedId [ , scopedId ]* } becomes { portDec [ , portDec ]* } [ assuming { property } ] connectionAction ::= includes connectionDec
Figure 6. Syntax for describing architectures with π-ADL
| excludes scopedId
Once an architecture is described with π-ADL, it can be refined using refinement actions expressed with π-ARL as defined in Figure 7.
| replaces scopedId by connectionDec | where { scopedId [ , scopedId ]* } becomes { connectionDec [ , connectionDec ]* } [ assuming { property } ]
refinementApp := architecture id refines id using { [ scopedId:: ] refinementAction [ . [ scopedId:: ] refinementAction ]*
Figure 9. Syntax for applying port refinement
} [ assuming { property } ]
Behaviour refinement is defined in terms of transformations on behaviours as depicted in Figure 10.
refinementAction ::= types typeAction | values valueAction
behaviourAction ::= behaviour becomes behaviourExp
| ports portAction
[ assuming { property } ]
| connections ( connectionAction | connectingAction ) | behaviour behaviourAction
Figure 10. Syntax for applying behaviour refinement
| components componentAction
Finally, structure refinement is defined in terms of transformations on components, connectors, and connections as depicted in Figure 11.
| connectors connectorAction
Figure 7. Syntax for applying refinement actions 9
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) quests for the data of a certain key by sending the data value stored under this key.
componentAction ::= includes componentDec | excludes scopedId
Figure 12 depicts the data acquisition system as a whole. It is represented as a component, named DasDef, having ports7 update and request. These ports represent the interaction of the DasDef system with its environment.
| replaces scopedId by componentDec | where { scopedId [ , scopedId ]* } becomes { componentDec [ , componentDec ]* } [ assuming { property } ] | explodes scopedId | implodes { scopedId [ , scopedId ] } as componentDec
key in
update
request
connectorAction ::= includes connectorDec DasDef
| excludes scopedId
data
| replaces scopedId by connectorDec
Figure 12. The system as a whole
| where { scopedId [ , scopedId ]* }
Using π-ADL, the DasDef system abstraction can be formally described as shown in Figure 13.
becomes { connectorDec [ , connectorDec ]* } [ assuming { property } ] | explodes scopedId
architecture DasDef is abstraction() {
| implodes { scopedId [ , scopedId ] } as connectorDec
type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. port update is {connection in is in(Entry) }.
connectingAction ::=
port request is { connection key is in(Key).
unifies { scopedId [ , scopedId ]* } with { scopedId [ , scopedId ]* }
connection data is out(Data)
| relays { scopedId [ , scopedId ]* } with { scopedId [ , scopedId ]* }
} assuming {
| separates { scopedId [ , scopedId ]* } from { scopedId [ , scopedId ]* }
protocol is { ( via key receive any. true*. via data send any )* } }.
Figure 11. Syntax for applying structure refinement
…
5. Case Study
}
In order to illustrate how π-ARL can be used to formally refine a Figure 13. Ports of the Architecture software architecture, we present in this section a simple case study on the stepwise refinement of the abstract architecture of a In this interface description of the data acquisition system, type data acquisition system (see [30] for a more complex and complete Key is the set of all possible key values and type Data is the set of case study). all possible data values. Entry is the tuple type tuple[Key, Data], First we will present the abstract architecture description of the i.e. the set of all possible entries associating key and data values. data acquisition system as it is specified with π-ADL in [29]. Then Two ports are declared: update that comprises the connection in we will refine the abstract architecture in order to obtain a more for receiving entries and request that comprises the connections concrete architecture where performance is improved. Finally the key and data for answering requests. The protocol enforced by this resulting architecture obtained from the application of the refine- port is that requests for the data of a certain key, which are received via the connection key, are answered by sending (after ment actions is presented. processing) a data value via the connection data. For each key received there must be a data sent before accepting the next key. 5.1 Architecture Description with π-ADL To start, let us present the abstract architecture description of the data acquisition system. We will present a black-box description of the architecture focusing on interface (i.e. ports and their connections) of components and connectors. Then we will add, as an example, the internal behaviour of a connector. Finally the encompassing structure (i.e. binding among components and connectors using connection unifications) is described. The data acquisition system receives pairs of key and data: a key and a data value to be stored under this key. New data values for the same key overwrite old values. Concurrently, it answers re-
The data acquisition system is composed of a sensor and a data manager. The sensor acts as a client of the data manager that acts as a server managing the sensor’s acquired data. The raw data received from the environment first undergoes some processing in the sensor and is then forwarded to the remote data manager that stores the data. Figure 14 outlines the abstract architecture of the system in terms of its components and connectors.
7
10
By syntactic convention, ports that are not explicitly declared as restricted are external free ports.
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) key values and the connection data for sending the data value stored under this key, and incoming for receiving entries. connector LinkDef is abstraction() {
update
request
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
DasDef
port incoming is { connection toLink is in(Entry) }. port outgoing is { connection fromLink is out(Entry) }. outgoing
incoming
outgoing
incoming
incoming
select
…
LinkDef SensorDef
DataManagerDef
} assuming { protocol is { (
Figure 14: Outline of the architecture
via incoming::toLink receive entry : Entry. via outgoing::fromLink send entry )* }
The architecture consists of a sensor component SensorDef, a data manager component DataManagerDef, and a connector LinkDef to connect them together. These components and connector can be formally declared in π-ADL as follows. component SensorDef is abstraction() { type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. port incoming is { connection in is in(Entry) }. port outgoing is { connection toLink is out(Entry) }.
}
Figure 17. Ports of the connector Link In connector LinkDef (see Figure 17), two ports are declared: incoming that comprises the connection toLink for receiving entries and outgoing that comprises the connection fromLink for forwarding these entries. The protocol enforced by the two ports is that entries received via the connection toLink are immediately forward by sending it via the connection fromLink. This black-box description of the DasDef system architecture can be further detailed to achieve a white-box description of the architecture that encompasses interface, behavioural and then structural aspects. For instance, the behaviour of the connector LinkDef can be formally described in π-ADL as follows8.
… } assuming { protocol is { ( via incoming::in receive any. true*. via outgoing::toLink send any )* } }
connector LinkDef is abstraction() {
Figure 15. Ports of the component Sensor
…
In component SensorDef (see Figure 15), two ports are declared: incoming that comprises the connection in for receiving entries and outgoing that comprises the connection toLink for forwarding these entries. The protocol enforced by the two ports is that a value received via the connection in is (after processing) forward by sending some (possibly processed) value via the connection toLink. For each entry received there must be a value sent before accepting the next entry.
behaviour is { via incoming::toLink receive entry : Entry. via outgoing::fromLink send entry. behaviour() } } assuming { … }
Figure 18. Behavior of the connector Link
component DataManagerDef is abstraction() {
In connector LinkDef (see Figure 18), the behaviour specifies that entries received via the connection toLink are immediately forward by sending it via the connection fromLink. The behaviour is recursively defined. Once an entry is handled, it continues with the same (recursive) behaviour for the next entry.
type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. port select is { connection key is in(Key). connection data is out(Data) } assuming {
Using the components SensorDef and DataManagerDef and the connector LinkDef, the abstract architecture DasDef can be composed in π-ADL as shown in Figure 19, thereby providing the structure of the architecture in terms of attached components and connector.
protocol is { ( via key receive any. true*. via data send any )* } }. port incoming is { connection fromLink is in(Entry) }. … }
Figure 16. Ports of the component Data Manager In component DataManagerDef (see Figure 16), two ports are declared: select that comprises the connection key for receiving
8
11
See §5.3 for the formal description of behaviours of components.
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) the data manager stores the key and related data in its database.
architecture DasDef is abstraction() { … behaviour is
}
compose { sensor
is SensorDef()
and
link
is LinkDef()
and
dataManager
is DataManagerDef()
where {
sensor::incoming relays update
and
sensor::outgoing unifies link::incoming
and
link::outgoing unifies dataManager::incoming
and
request relays dataManager::select }
One possible architectural refinement to achieve this architecture is to introduce two components, compressor and uncompressor, that compress and uncompress the data, respectively. In the sequel, we present how this refinement can be carried out with π-ARL by a software architect. The abstract architecture to be refined was depicted in Figure 14. It is depicted again in the following figure, where connections are shown and ports have been hidden.
} key
Figure 19. Composition of the Architecture in
In the architecture, the component instances sensor and dataManager are connected using the connector link. In order to actually connect them, connections must be unified9. Connection toLink of port outgoing of component sensor is unified with connection toLink of port incoming of connector link. Connection fromLink of port outgoing of connector link is unified with connection fromLink of port incoming of component dataManager. Besides connecting component instances together, the architecture must express the binding between external ports and ports of components. This binding is expressed by connection relay. Connection in of external port update is relayed to connection in of port incoming of component sensor. Connection key of external port request is relayed to connection key of port select of component dataManager. Connection data of port select of component dataManager is relayed to connection data of external port request.
toLink
toLink
fromLink
fromLink
LinkDef SensorDef
DataManagerDef
DasDef
Figure 20. Outline of the abstract architecture 1st step: adding components As first step, the architect could introduce the two new empty components, Compressor and Uncompressor. They should not be connected to any other component in the architecture. The following figure depicts the architecture after this refinement step.
5.2 Architecture Refinement with π-ARL The software architect can refine the previously described abstract architecture to obtain a more concrete architecture where performance is improved. This could be achieved by reducing the transmission time for the entries: for each entry the sensor will compress the data to transmit it and the data manager will uncompress to store it. The compressed data is supposed to be much smaller in size than the data itself and the gain in the transmission time compensates the time for compressing and uncompressing the data.
key in
toLink
t oLink
fromLink
fromLink
LinkDef SensorDef
Dat aManagerDef
Compressor
Uncompressor
data
The architect is not interested in the algorithmic aspects of the DasRef1 computation of the data compression. S/he just consider that the compressed data is itself an element of Data, and that there is a function compress : Data → Data that compress the data. Another Figure 21. Adding new disconnected components function uncompress : Data → Data uncompress the data. S/he In π-ARL, this refinement could be expressed as follows. assumes that for all data: uncompress(compressed(data)) = data. In order to refine the architecture, the following actions could be carried out. The sensor could be extended with a compressor. For each new entry the data related to a key is compressed and forwarded. The remote data manager could be extended with a uncompressor. It reads the input, uncompress the received data and 9
data
If connections have the same names in different ports, identifying ports is enough to express unifications (if connection names are different, then they must be explicitly unified). 12
architecture DasRef1 refines DasDef using { components includes { component Compressor is abstraction() { deferred } }. components includes { component Uncompressor is abstraction() { deferred } } }
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
It is worth noting that these refinement actions do not change the 3rd step: adding input connections behaviour of the architecture. The architect could now add an input connection fromCSLink to Compressor, and an input connection fromCoLink to Uncompres2nd step: adding output connections sor. S/he could also add an input connection fromUDLink to The architect could now add a typed output connection toCoLink DataManager. to Compressor and a typed output connection toUDLink to Uncompressor. S/he could also add an output connection toCSLink to The following figure depicts the architecture after this refinement step. Sensor. The following figure depicts the architecture after this refinement step.
key in
toLink
toLink
fromLink
fromLink
LinkDef SensorDef
Dat aManagerDef
toCSLink
fromUDLink
fromCSLink
toUDLink
data
key in
toLink
toLink
fromLink
fromLink
LinkDef SensorDef
DataManagerDef
data
toUDLink
toCSLink
fromCoLink
toCoLink
toCoLink
Unc ompressor
Compressor
Unc ompressor
Compressor
DasRef2/DasRef3
DasRef4
Figure 22. Adding output connections to components
Figure 23. Adding input connections to components
In π-ARL, this refinement could be expressed as follows. architecture DasRef2 refines DasRef1 using {
In π-ARL, this refinement could be expressed as follows. architecture DasRef4 refines DasRef3 using {
Compressor::types includes
Compressor::connections includes
{ type Key is Any. type Data is Any. type Entry is tuple[Key, Data] }.
{ connection fromCSLink is in(Entry) }
Uncompressor::types includes
Uncompressor::connections includes
{ type Key is Any. type Data is Any. type Entry is tuple[Key, Data] }
{ connection fromCoLink is in(Entry) }
}
DataManagerDef::incoming::connections includes { connection fromUDLink is in(Entry) } }
architecture DasRef3 refines DasRef2 using { Compressor::connections includes { connection toCoLink is out(Entry) }. Uncompressor::connections includes { connection toUDLink is out(Entry) }. SensorDef::connections includes
Since these connections are restricted inside the architecture and are not previously connected to any component, the conditions of the refinement action for the addition of input connections are satisfied. The behaviour of the system itself is unchanged, since the new connections are not used in the architecture.
{ connection outgoing::toCSLink is out(Entry) }
4th step: adding and connecting connectors The architect could now add connectors CoLink to connect the compressor and the uncompressor, CSLink to connect the comSince these connections are restricted inside the architecture and are not previously connected to any component, the conditions of pressor and the sensor, and DDLink to connect the uncompressor the refinement actions for the addition of output connections are and the data manager. satisfied. The following figure depicts the architecture after this refinement Note that the behaviours of the components that have been added step. are completely undefined. The behaviour of the system itself is unchanged, since the new connections are not used in the architecture. 13 }
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) architecture DasRef5 refines DasRef4 using { connectors includes {
key in
toLink
toLink
fromLink
fromLink
connector CoLink is abstraction() {
LinkDef SensorDef
Dat aManagerDef
toCSLink
fromUDLink
data
type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. connection toCoLink is in(Entry). connection fromCoLink is out(Entry).
toCSLink
behaviour is { deferred }
fromUDLink
}. CSLink
connector CSLink is abstraction() {
UDLink
type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. fromCSLink
toUDLink
fromCSLink
toUDLink
connection toCSLink is in(Entry). connection fromCSLink is out(Entry). behaviour is { deferred } }.
toCoLink
toCoLink
connector UDLink is abstraction() {
fromCoLink fromCoLink CoLink
Compressor
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
Uncompressor
connection toUDLink is in(Entry). DasRef5
connection fromUDLink is out(Entry). behaviour is { deferred }
Figure 24. Adding and connecting connectors
}.
In π-ARL, this refinement could be expressed as follows.
connections unifies CoLink::toCoLink with Compressor::toCoLink. connections unifies CoLink::fromCoLink with Uncompressor::fromCSLink. connections unifies CSLink::toCSLink with SensorDef::outgoing::toCSLink. connections unifies CSLink::fromCSLink with Compressor::fromCSLink. connections unifies UDLink::toUDLink with Uncompressor::toUDLink. connections unifies UDLink::fromUDLink with DataManagerDef::incoming::fromUDLink }
Off course, the addition of connectors will, as they are first-class citizens as components, follow the same basic steps: addition of connectors without connections, addition of output connections, and addition of input connections. The behaviour of the system itself is unchanged, since the connections toCSLink and fromUDLink added to the sensor and the data manager respectively are not yet used by their behaviours in the architecture. 5th step: refining the behaviour of added components The architect could now refine the behaviour of added components in π-ARL. The Compressor and Uncompressor components are refined as follows.
14
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
architecture DasRef6 refines DasRef5 using {
architecture DasRef8 refines DasRef7 using {
Compressor::behaviour becomes abstraction() {
component Sensor refines SensorDef using {
compress is function(d : Data) : Data { deferred }.
connections replaces outgoing::toLink by outgoing::toCSLink
replicate
}.
via fromCSLink receive entry.
component DataManager refines DataManagerDef using {
via toCoLink send tuple(entry::key, compress(entry::data))
connections replaces incoming::fromLink by incoming::fromUDLink
}.
}
Uncompressor::behaviour becomes abstraction() {
}
uncompress is function(d : Data) : Data { deferred }.
The architect assumes that compressing and uncompressing the processed data via CoLink yields the same data as that transmitted through Link. Formally:
replicate via fromCoLink receive entry. via toUDLink send tuple(entry::key, uncompress(entry::data))
∀ d : Date • uncompress(compress(d)) = d
}
That is, in order to guarantee that the value-passing behaviour of the new architecture refines the value-passing behaviour of the abstract architecture, the architect assumes that this property will The compressor applies the compress function to the data received hold in the system. In fact, it becomes a proof obligation. This from its input connection to send the compressed data via its out- assumption-guarantee is expressed in π-ARL as follows. Thereby, put connection. The uncompressor applies the uncompress func- if the assumption holds, the refinement is guaranteed. tion to the data received from its input connection to send the uncompressed data via its output connection. architecture DasRef8bis refines DasRef8 assuming { }
As the behaviour of these components were unspecified, that is their specifications were deferred until now, this refinement is obviously correct. The structure of the system remains unchanged.
property dataIntegrity is { forall d : Data | uncompress(compress(d)) = d } }
The following figure depicts the resulting architecture after these 6th step: refining the behaviour of added connectors latter refinement steps. The architect could now refine the behaviour of added connectors to carry the data by CSLink, the compressed data by CoLink and the uncompressed data by UDLink. This is accomplished by refinkey ing the behaviour of these connectors as follows. in
toLink
fromLink LinkDef
architecture DasRef7 refines DasRef6 using {
Sensor
DataManager
toCSLink
fromUDLink
toCSLink
fromUDLink
CSLink
UDLink
fromCS Link
t oUDLink
fromCS Link
t oUDLink
CSLink::behaviour becomes abstraction() { replicate via toCSLink receive entry : Entry. via fromCSLink send entry }. CoLink::behaviour becomes abstraction() { replicate via toCoLink receive entry : Entry. via fromCoLink send entry }. UDLink::behaviour becomes abstraction() { replicate via toUDLink receive entry : Entry. via fromUDLink send entry } } toCoLink
toCoLink
fromCoLink fromCoLink CoLink
7th step: refining the behaviour of existing components The architect could now refine the behaviour of existing components of the abstract architecture in order to take into account the new introduced components and connectors. This is accomplished by refining the behaviour of the sensor and data manager as follows. 15
Compressor
Uncompressor
DasRef8/DasRef8bis
Figure 25. Reconnecting connections of Sensor and DataManager
data
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
8th step: removing disconnected connectors After this refinement, the connector LinkDef is no more used and can therefore be discarded by the architect.
key in
architecture DasRef9 refines DasRef8bis using {
Sensor
DataManager
toCSLink
fromUDLink
toCSLink
fromUDLink
CSLink
UDLink
fromCSLink
toUDLink
fromCSLink
toUDLink
data
connectors excludes LinkDef }
The following figure depicts the resulting architecture after this last refinement step.
key in Sensor
DataManager
toCSLink
fromUDLink
toCSLink
fromUDLink
data
toCoLink
t oCoLink
fromCoLink fromCoLink CoLink
Compressor
CSLink
UDLink
fromCSLink
toUDLink
fromCSLink
toUDLink
toCoLink
t oCoLink
Uncompressor
DasRef9
Figure 27. Imploding sub-architectures as components Imploding sub-architectures as components yielding a composite sensor and a composite data manager is expressed in π-ARL as follows.
fromCoLink fromCoLink CoLink
Compressor
architecture DasConc refines DasRef9 using {
Uncompressor
components implodes { Sensor and CSLink and Compressor } DasRef9
as CoSensor. components implodes { DataManager and UDLink and Uncompressor }
Figure 26. Removing a connector
as CoDataManager }
9th step: imploding sub-architectures as components In the last refinement step, in order to get a concrete architecture The following figure shows the same architecture after that rethat has higher performance, and is yet platform-independent, the finement step. architect will implode the sensor and the compressor as one component and the data manager and the uncompressor as another key component. in
The following figure depicts the architecture before this refinement step.
toCoLink
toCoLink
fromCoLink fromCoLink CoLink
CoSensor
CoDataManager
data
DasConc
Figure 28. Definition of the concrete architecture 5.3 Description of the Resulting Refined Architecture The application of all these refinement steps yields a more concrete architecture. The architecture that is obtained by refinement is equivalent to the following architecture in π-ADL. A composite refinement action can be defined and reused in π-ARL by combining these different refinement steps in order to capitalize this refinement expertise. 16
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) The sub-components and sub-connector of composite component CoSensor are described in π-ADL as follows.
architecture DasConc is abstraction() { type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
component Sensor is abstraction() {
port update is { connection in is in(Entry) }.
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
port request is { connection key is in(Key).
port incoming is { connection in is in(Entry) }.
connection data is out(Data)
port outgoing is { connection toCSLink is out(Entry) }.
} assuming {
behaviour is abstraction() {
protocol is { ( via key receive any. true*. via data send any )* } }.
process is function(d: Data) : Data { deferred }.
behaviour is compose { CoSensor and CoLink and CoDataManager }
replicate
via in receive entry. via toCSLink send tuple(entry::key, process(entry::data))
}
}
The two composite components CoSensor and CoDataManager and the connector CoLink are described in π-ADL as follows.
} assuming { protocol is { ( via incoming::in receive any. true*.
component CoSensor is abstraction() {
via outgoing::toCSLink send any )* }
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
}
port incoming is { connection in is in(Entry) }. port outgoing is { connection toCoLink is out(Entry) } behaviour is compose { Sensor and CSLink and Compressor }
component Compressor is abstraction() {
} assuming {
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
protocol is { ( via incoming::in receive any. true*.
connection fromCSLink is in(Entry).
via outgoing::toCoLink send any )* }
connection toCoLink is out(Entry).
}
behaviour is abstraction() { compress is function(d : Data) : Data { deferred }. replicate
component CoDataManager is abstraction() {
via fromCSLink receive entry. via toCoLink send tuple(entry::key, compress(entry::data))
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
}
port select is { connection key is in(Key).
}.
connection data is out(Data) } assuming { protocol is { ( via key receive any. true*. via data send any )* }
connector CSLink is abstraction() {
}.
type Key is Any. type Data is Any. type Entry is tuple[Key, Data].
port incoming is { connection fromCoLink is in(Entry) }.
connection toCSLink is in(Entry).
behaviour is compose { DataManager and UDLink and Uncompressor }
connection fromCSLink is out(Entry).
}
behaviour is abstraction() { replicate
via fromCSLink send entry
connector CoLink is abstraction() { }
type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. }
connection toCoLink is in(Entry). connection fromCoLink is out(Entry). behaviour is abstraction() {
via toCSLink receive entry.
The sub-components and sub-connector of composite component CoDataManager are described in π-ADL as follows.
replicate via toCoLink receive entry. via fromCoLink send entry } }
17
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004) 6. Related Work Refinement is a key issue on supporting formal development. There are different formal description techniques supporting refinement providing specific constructs to develop a concrete specification from an abstract one.
component DataManager is abstraction() { type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. port select is { connection key is in(Key). connection data is out(Data) } assuming {
Indeed, refinement mechanisms are provided by different formal description/development techniques such as B [1], Z [12], VDM [13], CSP [16], and UNITY [24], and semi-formal methods such as Catalysis [11], however with no architectural support.
protocol is { ( via key receive any. true*. via data send any )* } }. port incoming is { connection fromCoLink is in(Entry) }.
At our knowledge, with the exception of a variant of FOCUS [38], i.e. FOCUS/DFA [33], RAPIDE [19][34] and SADL [25][26], there is no proposal for a rigorous calculus based on architectural terms as there are rigorous calculus for refinement of programs [5][6].
behaviour is abstraction() { database is location(Set() : Entry). replicate choose { via fromLink receive entry. database := database’ including(entry) or via key receive queryKey : Key. via data send (database’ selecting(d | d::key == queryKey) } } }
component Uncompressor is abstraction() { type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. connection fromCoLink is in(Entry). connection toUDLink is out(Entry). behaviour is abstraction() { uncompress is function(d : Data) : Data { deferred }. replicate
via fromCoLink receive entry.
via toUDLink send tuple(entry::key, uncompress(entry::data)) } }
connector UDLink is abstraction() { type Key is Any. type Data is Any. type Entry is tuple[Key, Data]. connection toUDLink is in(Entry). connection fromUDLink is out(Entry). behaviour is abstraction() { replicate via toUDLink receive entry. via fromUDLink send entry } }
FOCUS in itself does not addresses refinement of software architectures, however a variant of FOCUS presents a proposal based on FOCUS to refine Data-Flow Architectures (FOCUS/DFA). It is based on the addition and removing of connections and components. Behaviour in FOCUS/DFA is described as a relation over input and output communication histories that obey certain causality constraints. It uses streams to describe communication histories on asynchronous channels. RAPIDE supports refinement through the mechanism of “maps between architecture descriptions”. The purpose of maps is to define how the executions of one architecture may be interpreted (or viewed) as executions of another architecture. RAPIDE allows two uses of maps: (i) as constraints, and (ii) as domains of maps. In RAPIDE there are no architectural primitives for supporting architecture refinement. SADL has been specially designed for supporting architecture refinement. In SADL, different software architectures are related by refinement mappings. However, SADL requires that the concrete architecture must be a faithful implementation of the abstract one, which makes the refinement too rigid for taking into account deferred design decisions. In the case of SADL the refinement is only structural. In the case of RAPIDE it is only behavioural (supported by simulations). In both cases, clear architectural primitives for refining architectures are not provided and the refinement supported is only partial. π-ARL, like refinement notations provided in the B and Z formal methods, provides operations to transform specifications. However, unlike FOCUS, B, and Z, π-ARL has been specially designed to deal with architectural elements. Unlike SADL, π-ARL supports underspecification. In FOCUS/DFA, refinement is essentially logical implication. In SADL, it is restricted by faithful interpretation. In RAPIDE, it is defined by simulations. In π-ARL, it is based on property implication, where the properties to be preserved are defined by the architect.
Work on architecture-based formal development has mainly concentrated on formal specification of software architectures. The issue on architecture refinement remains an open research issue, in particular with respect to the definition of an architectural refine18
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
ment calculus. π-ARL is a major step towards that goal: the definition of a formal refinement calculus based on architectural terms. A detailed positioning of π-ADL with respect to the state-of-art is given in [28].
Ongoing work is mainly related to completing the development of both the π-ADL and π-ARL toolsets in the ArchWare European Project [32]. These tools are integrated through a software process support system [15]. An XML-based notation [39] supports architecture description interchange among the tools.
7. Conclusion
Both π-ADL and π-ARL have been applied in several realistic π-ARL is an architecture refinement language for the stepwise case studies and industrial business cases at Thésame (France) and refinement of software architectures. Engineering Ingegneria Informatica (Italy). The pilot project at π-ARL provides a novel language that on the one side has been Thésame aims to architecting and refining agile integrated indusspecifically designed for architectural refinement taking into ac- trial process systems. The pilot project at Engineering Ingegneria count behaviour, port, structure, and data refinement from an ar- Informatica aims to architecting and refining federated knowledge chitectural perspective and on the other side is based on process- management systems. driven preservation of properties. The core of π-ARL is a set of architecture refinement primitives that supports transformation of architecture descriptions. Transformations are refinements if they preserve properties of the more abstract architecture. Core properties are built-in. Style-specific or architecture-specific properties are user defined. The underlying foundation for architected behaviours is the higher-order typed πcalculus.
Future work is mainly related with the formal development of an architecture-centric formal method. This formal method, called the π-Method, like formal methods such as B, FOCUS, VDM, and Z, aims to provide full support for formal description and development. Unlike these formal methods that do not provide any architectural support, the π-Method has been built from scratch to support architecture-centric formal software engineering.
References Furthermore, π-ARL provides a notation to express assumptions [1] Abrial J.-R.: The B-Book: Assigning Programs to Meanings. Camas properties of architectures [2]. It combines predicate logic with bridge University Press, 1996. temporal logic in order to allow the specification of both structural [2] Alloui I., Garavel H., Mateescu R., Oquendo F.: The ArchWare Architecture Analysis Language: Syntax and Semantics. Deliverable properties and behavioural properties.
D3.1b, ArchWare European RTD Project, IST-2001-32360, January
Regarding structural properties, the property notation is based on 2003. predicate logic. Regarding behavioural properties, it is based on [3] Alloui I., Oquendo F.: The ArchWare Architecture Description Language: UML Profile for Architecting with ArchWare ADL. Demodal µ-calculus [18]. The choice of modal µ-calculus as the unliverable D1.4b, ArchWare European RTD Project, IST-2001-32360, derlying formalism provides a significant expressive power [37]. June 2003.
Assumptions are proof obligations to guarantee the correctness of [4] Alloui I., Oquendo F.: Describing Software-intensive Process Archithe descriptions. tectures using a UML-based ADL. Proceedings of the 6th International Conference on Enterprise Information Systems (ICEIS’04),
A major impetus behind developing formal languages for architecPorto, Portugal, April 2004. tural refinement is that their formality renders them suitable to be [5] Back, R-J.: Refinement Calculus, Part II: Parallel and Reactive Promanipulated by software tools. The usefulness of an architecture grams. Stepwise Refinement of Distributed Systems: Models, Forrefinement language is thereby directly related to the kinds of malisms, Correctness. J.W. de Bakker, W.P. de Roever, and G. Rozenberg (Eds.), LNCS, Springer-Verlag, 1990. tools it provides to support architecture-centric development [32]. Indeed, both π-ADL and π-ARL are supported by a comprehen- [6] Back, R-J., von Wright, J.: Refinement Calculus, Part I: Sequential Nondeterministic Programs. Proceedings of REX Workshop for Resive integrated toolset for supporting architecture-centric formal finement of Distributed Systems. LNCS, Springer-Verlag, 1989. description and development. It is composed of: [7] Bolusset T., Oquendo F.: Formal Refinement of Software Architec-
• • • • •
tures Based on Rewriting Logic, ZB2002 International Workshop on a π-ADL visual modelling tool [4], implemented as an extenRefinement of Critical Systems: Methods, Tools and Experience, sion of the Objecteering UML Modeller, Grenoble, Janvier 2002. a π-ADL callable compiler and a persistent virtual machine, [8] Brown A.W.: An Introduction to Model Driven Architecture – Part I: a π-ADL/π-ARL verification tool based on CADP [14][21] MDA and Today’s Systems. The Rational Edge, February 2004. and XSB Prolog, [9] Chaudet C., Greenwood M., Oquendo F., Warboys B.: Architecturethe π-ARL Refiner [22]: a π-ADL refinement tool providing a Driven Software Engineering: Specifying, Generating, and Evolving process-centred refinement framework based on the Maude Component-Based Software Systems. IEE Journal: Software Engineering, Vol. 147, No. 6, UK, December 2000. rewriting logic system [7][20], a π-ADL-to-Code synthesizer, from which a π-ADL-to-Java [10] Chaudet C., Oquendo F.: A Formal Architecture Description Language Based on Process Algebra for Evolving Software Systems. code generation tool has been synthesized. Proceedings of the 15th IEEE International Conference on Auto-
mated Software Engineering (ASE’00). IEEE Computer Society, Satisfying proof obligations in π-ARL is supported by the refineGrenoble, September 2000. ment and verification tools, including the refinement engine interpreting π-ARL and orchestrating a model checker, a prover and [11] D’Souza, D.F., Wills, A.C.: Objects, Components and Frameworks with UML: The Catalysis Approach. Addison-Wesley, 1998. specific evaluators.
19
ACM Software Engineering Notes
Volume 29, Issue 5 (September 2004)
[12] Davies J., Woodcock J.: Using Z: Specification, Refinement and Proof. Prentice Hall International Series in Computer Science, 1996. [13] Fitzgerald J., Larsen P.: Modelling Systems: Practical Tools and Techniques for Software Development. Cambridge University Press, 1998. [14] Garavel H., Lang F., Mateescu R.: An Overview of CADP 2001. European Association for Software Science and Technology (EASST) Newsletter, Vol. 4, August 2002. [15] Greenwood M., Balasubramaniam D., Cimpan S., Kirby N.C., Mickan K., Morrison R., Oquendo F., Robertson I., Seet W., Snowdon R., Warboys B., Zirintsis E.: Process Support for Evolving Active Architectures, Proceedings of the 9th European Workshop on Software Process Technology, LNCS 2786, Springer Verlag, Helsinki, September 2003. [16] Hinchey M.G., Jarvis S.A.: Concurrent Systems: Formal Development in CSP, McGraw-Hill, 1995. [17] IEEE Std 1471-2000: IEEE Recommended Practice for Architectural Description of Software-Intensive Systems, October 2000. [18] Kozen D.: Results on the Propositional µ-Calculus. Theoretical Computer Science 27:333-354, 1983. [19] Luckham D.C., Kenney J.J., Augustin L.M., Vera J., Bryan D., Mann W.: Specification and Analysis of System Architecture Using RAPIDE. IEEE Transactions on Software Engineering, Vol. 21, No. 4, April 1995. [20] Martí-Oliet N., Meseguer J.: Rewriting Logic: Roadmap and Bibliography. Theoretical Computer Science, 2001. [21] Mateescu R., Garavel H.: XTL: A Meta-Language and Tool for Temporal Logic Model-Checking. Proceedings of the 1st International Workshop on Software Tools for Technology Transfer, Aalborg, Denmark, July 1998. [22] Megzari K., Oquendo F.: The ArchWare Architecture Refinement Toolset. Deliverable D6.3, ArchWare European RTD Project, IST2001-32360, April 2004. [23] Milner R.: Communicating and Mobile Systems: The Pi-Calculus. Cambridge University Press, 1999. [24] Misra J., Chandy K.M.: Parallel Program Design: A Foundation, Addison-Wesley, 1988. [25] Moriconi M., Qian X., Riemenschneider R.A.: Correct Architecture Refinement. IEEE Transactions on Software Engineering, Vol. 21, No. 4, April 1995.
[26] Moriconi M., Riemenschneider R.A.: Introduction to SADL 1.0: A Language for Specifying Software Architecture Hierarchies. Computer Science Laboratory, SRI International, Technical Report SRICSL-97-01, March 1997. [27] Oquendo F.: The ArchWare Architecture Description Language: Tutorial. Report R1.1-1, ArchWare European RTD Project, IST2001-32360, March 2003. [28] Oquendo F.: The ArchWare Architecture Refinement Language. Deliverable D6.1b, ArchWare European RTD Project, IST-200132360, December 2003. [29] Oquendo F.: π-ADL: An Architecture Description Language based on the Higher Order Typed π-Calculus for Specifying Dynamic and Mobile Software Architectures. ACM Software Engineering Notes, Vol. 29, No. 3, USA, May 2004. [30] Oquendo F.: Formally Refining Software Architectures with π-ARL: A Case Study. ACM Software Engineering Notes, Vol. 29, No. 5, USA, September 2004. [31] Oquendo F., Alloui I., Cimpan S., Verjus H.: The ArchWare Architecture Description Language: Abstract Syntax and Formal Semantics. Deliverable D1.1b, ArchWare European RTD Project, IST2001-32360, December 2002. [32] Oquendo F., Warboys B., Morrison R., Dindeleux R., Gallo F., Garavel H., Occhipinti C.: ArchWare: Architecting Evolvable Software. Proceedings of the 1st European Workshop on Software Architecture, LNCS 3047, Springer Verlag, St Andrews, UK, May 2004. [33] Philipps J., Rumpe B.: Refinement of Pipe and Filter Architectures. Proceedings of FM’99, Springer Verlag, LNCS 1708, 1999. [34] RAPIDE Design Team: Guide to the RAPIDE 1.0. Language Reference Manuals, Stanford University, July 1997. [35] Sangiorgi D.: Expressing Mobility in Process Algebras: First-Order and Higher-Order Paradigms. PhD Thesis, University of Edinburgh, 1992. [36] Sangiorgi D., Walker D.: The Pi-Calculus: A Theory of Mobile Processes. Cambridge University Press, 2001. [37] Stirling C.: Modal and Temporal Properties of Processes. Springer Verlag, 2001. [38] Stolen K., Broy M.: Specification and Development of Interactive Systems. Springer Verlag, 2001. [39] Verjus H., Oquendo F.: The ArchWare Architecture Description Language: XML Concrete Syntax. Deliverable D1.3b, ArchWare European RTD Project, IST-2001-32360, June 2003.
20