Algebraic Software Architecture Reconfiguration Michel Wermelinger1 and Jos´e Luiz Fiadeiro2 1
Departamento de Inform´ atica, Faculdade de Ciˆencias e Tecnologia Universidade Nova de Lisboa, 2825-114 Caparica, Portugal
[email protected] 2 Departamento de Inform´ atica, Faculdade de Ciˆencias Universidade de Lisboa, Campo Grande, 1700 Lisboa, Portugal
[email protected]
Abstract. The ability of reconfiguring software architectures in order to adapt them to new requirements or a changing environment has been of growing interest, but there is still not much formal work in the area. Most existing approaches deal with run-time changes in a deficient way. The language to express computations is often at a very low level of specification, and the integration of two different formalisms for the computations and reconfigurations require sometimes substantial changes. To address these problems, we propose a uniform algebraic approach with the following characteristics. 1. Components are written in a high-level program design language with the usual notion of state. 2. The approach combines two existing frameworks—one to specify architectures, the other to rewrite labelled graphs—just through small additions to either of them. 3. It deals with certain typical problems such as guaranteeing that new components are introduced in the correct state (possibly transferred from the old components they replace). 4. It shows the relationships between reconfigurations and computations while keeping them separate, because the approach provides a semantics to a given architecture through the algebraic construction of an equivalent program, whose computations can be mirrored at the architectural level.
1 1.1
Introduction Motivation
One of the topics which is raising increased interest in the Software Architecture (SA) community is the ability to specify how a SA evolves over time, in particular at run-time, in order to adapt to new requirements or new environments, to failures, and to mobility [28,6,36]. There are several issues at stake [27], among them: modification time and source Architectures may change before execution, or at run-time (called dynamic reconfiguration). Run-time changes may be triggered by the current state or topology of the system (called programmed reconfiguration [7]).
modification operations The four fundamental operations are addition and removal of components and connections. Although their names vary, those operators are provided by most reconfiguration languages (like [16,7,22,1]). In programmed reconfiguration, the changes to perform are given with the initial architecture, but they may be executed when the architecture has already changed. Therefore it is necessary to query at run-time the state of the components and the topology of the architecture. system state Reconfiguration must cause the least possible disruption [32] and the new system must be in a consistent state. 1.2
Related Work
Only few ADLs are able to express dynamism [23]. Darwin [20] only permits constrained dynamism: the initial architecture may depend on some parameters, and during run-time components may be replicated. Wright’s formalism is a bit cumbersome since it requires all distinct configurations to be uniquely tagged [1]. ACME’s proposal only allows for the specification of optional elements (i.e., components, connectors, and links) [26]. There has been also formal work in the area. Some of it uses two different formalisms to represent reconfigurations and computations [24,2,1,17] while other approaches are uniform [33,31,12,15], using some notion of rewriting. These works have some common drawbacks. First, the languages to represent computations are very simple and at a lowlevel: rewriting of labels [15], process calculi [24,17,2,1], term rewriting [33,12], graph rewriting [31]. They do not capture some of the abstractions used by programmers and often lead to cumbersome specifications. Second, the combination of reconfigurations and computations leads to additional, sometimes complex, formal constructs: [15] uses constraint solving, [24,1,2] define new semantics or language constructs for the process calculi, [12] must dynamically change the rewriting strategies, [31] imposes many constraints on the form of graph rewrite rules because they are used to express computation, communication, and reconfiguration. A result of these shortcomings is that reconfigurations are constrained ([15] uses only context-free rules and [1] does not handle systems with potentially infinite distinct configurations) or that the relationship between the reconfigurations and computations is complex [1,24] or not quite apparent [2,17]. 1.3
Approach
To overcome some of these disadvantages, we propose to use a uniform algebraic framework and a program design language with explicit state. The former allows us to represent both architectures and their reconfigurations, and to explicitly relate the computational with the architectural level in a direct and simple way. On the other hand, the language incorporates some of the usual programming constructs while keeping a simple syntax to be formally tractable.
To be more precise, components are written in a Unity-like language [11], and consist of a set of “if-then” commands with assignments to typed attributes. Attributes have explicit initialisation conditions and the state of a component is given as usual by a set of pairs attribute/value. The algebraic framework is Category Theory [25], which has several benefits for SA [10]. Among them, it has a graphical notation, it is independent of the language used to represent components thus being able to relate different languages [9], and it allows the formalisation of connectors and their construction [8,34,35]. Like [24,33,31,15], we represent architectures by labelled graphs showing the components and their interconnections. Additionally, the categorical framework provides a semantics, given by an operation that transforms the architectural diagram into an equivalent component representing the whole system on which computations are performed. This relates the architectural and computational levels. Reconfiguration is specified through algebraic graph rewriting [5], a formalism with many years of research into its theory and application. Together with the representation of components, the approach guarantees that components are removed in a quiescent state [16] (i.e., when not interacting with other components) and are introduced in a properly initialized state. To make the paper self-contained and accessible to a wider audience, it is written in an informal way, using mathematical definitions sparingly. Also, all needed algebraic notions are briefly introduced. To facilitate exposition, the second part deals with reconfigurations performed when the system is shut down, while the third part incorporates the notion of state, in order to deal with reconfigurations that have to be coordinated with on-going computations. 1.4
The Example
The example is inspired in the luggage distribution system used to illustrate Mobile Unity [29]. One or more carts move on a N units long track with the shape ? → ?? ?? ↑ ? A cart advances one unit at each step in the direction shown by the arrows. The i-th cart starts from a unit determined by an injective function start of i. Carts are continuously moving around the circuit. Their movement must be synchronised in such a way that no collisions occur at the crossing. We assume that track units 7 and 28 cross. Reconfigurations may be due not only to mobility but also to component upgrade: a cart may be replaced by one with a builtin lap counter. 1.5
Category Theory
Category Theory [25] is the mathematical discipline that studies, in a general and abstract way, relationships between arbitrary entities. A category is a collection
of objects together with a collection of morphisms between pairs of objects. A morphism f with source object a and target object b is written f : a → b or f a −→ b. Morphisms come equipped with a composition operator “;” such that if f : a → b and g : b → c then f ; g : a → c. Composition is associative and has identities ida for every object a. Diagrams are directed graphs—where nodes denote objects and arcs represent morphisms—and can be used to represent “complex” objects as configurations of smaller ones. For categories that are well behaved, each configuration denotes an object that can be retrieved through an operation on the diagram called colimit. Informally, the colimit of a diagram returns the “minimal” object such that there is a morphism from every object in the diagram to it (i.e., the colimit contains the objects in the diagram as components) and the addition of these morphisms to the original configuration results in a commutative diagram (i.e., interconnections, as established by the morphisms of the configuration diagram, are enforced). f
g
Pushouts are colimits of diagrams of the form b ←− a −→ c. By definition of colimit, the pushout returns an object d such that the diagram a<