Interconnecting Formalisms: Supporting Modularity, Reuse and Incrementality †
José Luiz Fiadeiro
Tom Maibaum
Department of Informatics, Faculty of Sciences, University of Lisbon Campo Grande, 1700 Lisboa, PORTUGAL
[email protected]
Department of Computing Imperial College of Science, Technology and Medicine 180 Queen's Gate, London SW7 2BZ, UK
[email protected]
Abstract The necessity to deal simultaneously with different formalisms seems to be intrinsic to the discipline of Software Engineering, particularly in relation to modularity, reusability and incremental ity. In order to accommodate this diversity of formalisms, some authors have proposed the adoption of a common semantic do main for the different specification languages, and their transla tion into a common style of predicate logic. In this paper, we sug gest that an alternative approach may be taken where the different modelling approaches are formalised individually in a common mathematical framework – Category Theory, and relationships are established between them using functors. Several examples are adduced to support this view and the generality of the approach is illustrated by formalising reusability as a property of a functor relating two such formalisms. Keywords: Reuse, incremental development, compositionality, multiperspective specification, formal methods, general systems theory
1
Introduction
The necessity to deal simultaneously with different formalisms seems to be intrinsic to the discipline of Software Engineering, particularly in relation to the issues of modularity, reusability and incrementality in software development. Several rationales may be adduced to justify this fact. These include the nature of the properties that one wishes to specify – one should be able to use a logic that is better suited for capturing the properties to be specified; the nature of the development task – some formalisms are better suited for specifying requirements, others for programming; and the nature of the components of the system that one is developing – mechanical components are usually specified in formalisms quite different from those used for software specification or, for that matter, for the representation of human or organisational agents. As an example, one may well wish to use simultaneously a transi___________________________________________________
† This work was partially supported by the Esprit BRA 8035 (MODELAGE), the HCM Scientific Network MEDICIS, JNICT under contract PBIC/C/TIT/1227/92 (IDD) and the Eureka project Eureka Soft ware Factory ©1995 by the Association for Computing Machinery, Inc. Permission to make digital or hard copies of part or all of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that new copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request Permissions from Publi cations Dept, ACM Inc. Fax 1(212)869-0481, or
[email protected]
tion system to specify the possible states and state transitions of a component, temporal logic to specify its liveness properties (actually, approaches to concurrent system specification exist [Lamport 89] that combine transition systems and temporal logic), a program to model a controller with which it interacts, and a deontic logic to prescribe the uses that a human agent may make of the combined system. Indeed, the principle that systems should be able to be understood, together with their environment, and developed in a modular way by interconnecting different pieces, possibly reusing previously developed components, requires this ability to deal with components specified or developed in different formalisms. Software development can no longer be seen to evolve, uniformly, through a succession of steps of a uniform and conceptually simple character, and with a clear boundary between system and environment. The scenario seems to have become more and more that of an evolving collection of interconnected objects, some of which are already developed software components, others are just specifications for components that need to be built from scratch, yet others are just specifications of activities currently performed by humans but that one may later on automate, etc, etc. As we abandon the illusion of ab initio software development, and explore ways of making it incremental by letting a system evolve through the addition and revision of components, we must be ready to accept that this sort of evolution will happen in a heterogeneous environment. Yet, we want to control the way this evolution takes place and be able to reason about the final behaviour of the system quite independently of subsequent decisions to actually put a program in place of a specification, automate an activity that was ensured previously by humans, etc. In order to accommodate this diversity of formalisms, some authors [e.g. Zave and Jackson 93] have proposed the adoption of a scheme where there is a common semantic domain for the differ ent specification languages and there is a translation into a common style of predicate logic. (See also [Niskier et al 89].) In this paper, we wish to suggest that an alternative approach may be taken and to point out its technical and methodological advantages. Rather than using a common semantic domain and syntactic representation for the different objects, we propose that the different modelling approaches be themselves formalised individually in a common mathematical framework – Category Theory, and that relationships be established between them using functors. The idea is that the integration that is necessary for being able to reason about the properties of a system can be effected by relating the way the different formalisms structure the application instead of the ontologies they use to model the universe of discourse. Indeed, it seems that the ability to support the intended discipline of modular and incremental development, namely to reuse previously developed components and/or designs, depends more on an agreement between the notions of module and module intercon-
tions for specifications, simulations for behaviours, etc. Functors, as mappings between the objects and morphisms of two categories, then tell us how two formalisms can be related at the level of their structural properties.
nection that the different formalisms support, than on any agreement based on the intended semantic domain. This is the point of view that we assume in the paper and for which we wish to propose Category Theory as a convenient mathematical framework. In section 2, we further motivate the use of Category Theory in this context. In section 3, we show how a program design language and a specification formalism can be formalised as categories. In section 4, we show how two formalisms can be brought together as a means of supporting system development in such a way that objects in either level can co-exist and be interconnected, and how a formalisation of the relationship between the two layers of abstraction involved in a development step allows us to discuss, with generality, the reusability of software components as suggested in [Krueger 92]. A glossary of the notation introduced throughout the paper is provided at the end.
2
That is, CT provides a mathematical infrastructure where the primitives are available for presenting and comparing formalisms in terms of the discipline of modularisation that they support. As indicated in the introduction, we believe this to be a key ingredient in supporting the use of multiple formalisms in software development. The rest of the paper will present the case in more detail, starting with an illustration of how program design languages and specification languages can be formalised as categories.
The categorical imperative
3
Programs and specifications
3.1
Categories of programs
In order to illustrate how CT can be used for formalising programming languages and their structuring principles, we use a paral lel program design language, which we call COMMUNITY , and that is in the style of IP (Interacting Processes) [Francez and Forman 90], UNITY [Chandy and Misra 88] and Action Systems [Back and Kurki-Suonio 88]. A complete account of the categorical formalisa tion of this language is given in [Fiadeiro and Maibaum 95] based on earlier work [Fiadeiro and Reichwein 92].
A general explanation of why and how Category Theory (CT) is useful in Computing has already been given in [Goguen 91]; it would be difficult for us to improve on it. Nevertheless, it seems important to state the basic principles which make it useful for the purpose at hand (and one that has previously not been extensively explored), namely to give evidence of its applicability for handling multiple formalisms in software development. A category consists of a collection of objects and, for every pair of objects, a collection of morphisms between them, together with an identity morphism for every object and an associative composition law of morphisms for which the identity morphisms are, indeed, identities. The intention is that, in order to model some notion of structure, we define a category whose objects have that structure and whose morphisms preserve it. Morphisms then become an engineering tool used to structure systems from compo nents.
In this setting, programs are built over signatures. Signatures are abstractions of the syntax of (application) programs. They are structures of symbols that account for the different ontologies of the paradigm chosen for software development. For instance, in the reactive paradigm that we are using for illustration, we must distinguish between three different classes of symbols: symbols accounting for the (atomic) actions that a software component may perform, symbols that account for the state of the component ("attributes"/"program variables"), and symbols that account for the data types in which the attributes take values.
A wide range of formalisms and modelling approaches supporting various software and systems engineering tasks have already been developed, with some of them cast in CT. For instance, as explained since the early 70s by J.Goguen [e.g., Goguen and Ginali 78], categorical techniques can be used in General Systems Theory for modelling a variety of behaviours, including physical components, where morphisms capture simulations. Similar principles have been used to formalise process models for concurrent systems [Sassone et al 93] such as transition systems, synchronisation trees, event structures, etc. Through institutions [Goguen and Burstall 84], the theories of a logic have been shown to constitute a category whose morphisms correspond to property preserving translations between their languages. Such mappings are also known as interpretations between theories and have been used, for instance, in [Lehman et al 84, Veloso et al 85] for modelling relationships between abstract and concrete specifications, or in [Moriconi and Qian 94] for modelling mappings between different notions of software architecture.
For simplicity, we assume that the data types are formalised through a signature Σ=(S,Ω) (the universe signature) in the usual algebraic sense [Ehrig and Mahr 85], i.e. S is a set (of sort symbols) and Ω is an S *×S-indexed family (of function symbols), to gether with a set of (first-order) axioms over Σ defining the properties of the operations. A signature of a component over such a universe defines the attributes and the actions of the component: Definition 1: A program signature is a triple (V,R, Γ) where • V and R are (disjoint) S-indexed families of sets (of attribute symbols). The union of V and R is denoted by Α. • Γ is a set (of action symbols). ❚ The family V corresponds to the local attributes of the program (its "variables"), i.e. those that the environment cannot write. For a given sort s, Vs is the set of names of the local attributes that take values in s. The family R corresponds to the attributes that are external, i.e. that the program needs to read from its environment. The family Α is the union of V and R: it corresponds to the attributes that are used in the program. We shall often denote a signature by θ=(Α=V⊕R,Γ ), or just θ=(Α,Γ) in contexts where the distinction between local and external attributes is not meaningful.
Indeed, we could even say that the ability to express a formalism as a category is a measure of the "quality" of the structuring principles that it is meant to capture. Hence, the advantage that is foreseen, and that we wish to make evident in the paper, of adopting a categorical framework for relating different formalisms is, basically, that it is based not only on the identification of the nature of the objects (programs, specifications, behaviours, etc) that are handled by the different formalisms, but also, and more importantly, on the identification of the structuring principles supported by the formalisms to which the categories correspond. These structuring principles are captured through the morphisms, e.g. superposition for parallel programs, property preserving transla-
Signature morphisms provide the mechanisms by which we can establish relationships between the signatures of different programs: Definition/Proposition 2: Given signatures θ 1=(Α 1=V 1⊕R1,Γ 1) and θ 2= ( Α2=V 2⊕R2,Γ 2), a signature morphism σ from θ 1 to θ2
– 2–
consists of a pair (σ α: Α1 → Α 2, σγ: Γ1 → Γ 2) of (total) functions such that σ (V1)⊆V 2. It is easy to prove that signatures and signature morphisms constitute a category p-SIGN . ❚
cept of superposition. In order to define these conditions, we need a way of translating between the terms and propositions that are used in programs:
Notice how the notion of signature morphism already captures part of the structural principles of the underlying paradigm. Assuming that morphisms capture relationships between a program and a system of which it is a part, local attributes of a program have to be mapped to local attributes of the system (i.e. the system cannot violate the locality – encapsulation – of the attributes of the components), but external attributes can be mapped to local ones of the system (i.e. what is external at the level of a program may be local at the level of a system that contains that program).
Definition 5: Given a signature morphism σ: θ 1 → θ 2, σ(t) ::= σ(a) | c | f( σ(t),…, σ(t)) σ(φ) ::= ( σ(t)= σ(t)) | ( σ(φ)→σ(φ)) | ¬ σ(φ)
That is, terms and propositions are translated by replacing the attributes by their translations. The logical structure of terms and propositions is preserved (logical operators are not translated) and function symbols remain unchanged because we assume that the available data types are fixed (a program cannot define new data types).
Programs are defined over signatures by detailing the way actions operate on the attributes and the circumstances in which they can occur in a computation. In order to formalise the effects of actions (assignments) and their preconditions, we need a way of denoting the application of operations of the data types to attributes.
Definition 6: A program morphism σ:( θ 1,∆ 1)→(θ 2,∆ 2) is a signa ture morphism σ:θ 1→θ 2 such that 1. For all a 1∈V 1, D2 (σ(a 1 ))=σ(D 1 (a 1 )) . 2. For all g1∈Γ 1, a1∈V 1, ‚θ2(B 2σ(g) → σ(F 1(g1,a1))=F2(σ(g 1),σ(a 1)). 3. ‚θ (I2 → σ(I 1)). 2 4. ‚θ (B2σ (g) → σ(B 1g)) for every g ∈Γ 1. ❚
Definition 3: Given a signature θ=(Α=V ⊕R,Γ ), the language of terms is defined as follows, for every sort s∈ S: t s ::= a | c | f(t s ,…,ts ) 1
n
for a ∈Α s, c∈Ω ,s and f∈Ω ,s. 1 n The language of propositions is defined as follows: φ ::= (ts=st s) | (φ→φ ) | (¬φ)
2
In this definition ‚ stands for the consequence relation of the logic associated with the language introduced in definition 3. See [Fiadeiro and Maibaum 95] for details.
❚
Definition 4: A program is a pair (θ ,∆) where θ is a signature and ∆ is a triple (I,F,B) where • I is a θ -formula (constraining the initial values of the attributes). • F is a Γ-indexed set of statements , where a statement is a partial assignment of terms to attributes; we denote by F(g,a) the term assigned to a ∈V and by D(g) the domain of F(g) (the set of attributes that g can change); we also define D(a)={g∈Γ | a ∈D(g)} – the set of actions that can change a ; • B is a Γ-indexed set of propositions (giving for each action its guard). ❚
This notion of program morphism captures what is called in [Francez and Forman 90] regulative superposition . Requirement 1 corresponds to the locality condition: local attributes remain unchanged by actions that do not belong to the base program. Requirement 2 corre sponds to the preservation of the functionality of the base pro gram: the effects of its actions are preserved. Requirement 3 implies that every properly initialised computation for (θ 2,∆ 2) is also properly initialised for (θ 1,∆ 1). Requirement 4 corresponds to the strengthening of the guards (or, more accurately, to the non-weak ening of the guards). It implies that safe computations for ( θ 2,∆ 2) are also safe for ( θ1,∆ 1). Liveness, how ever, may not be preserved be cause guards can be strengthened.
These definitions are expressive enough to model the basic features of parallel programs: each action g defines the following guarded assignment [B → || a:=F(g,a)] g
As an example of a morphism consider the following programs, where p and q are conditions on the variables of the programs, and initialisations have been omitted: P1 ≡ var a : int do g 1 : [p → a := 1] P2 ≡ var a, b : int do g 2 : [p∧q → a,b := 1,a+1] [] h 2 : [¬q → b := a+1]
a∈D(g)
where the notation || is being used for denoting multiple assign ments, i.e. an assignment (a,b:=a+b,a–b) can be de noted by (a:=a+b)|| (b:=a–b). If V is empty (e.g. when the component is a simple communication channel), any of its actions is typed with an empty statement (denoted by skip ).
All the conditions in definition 6 are satisfied by the mapping .
A COMMUNITY program P=(θ ,∆), where θ =(V,R,Γ) and ∆=(I,F,B), is denoted as follows: P ≡ read R var V init I do [] g: [B g → g∈Γ
||
a∈D(g)
❚
Proposition 7: Programs and their morphisms form a category PROG . ❚ In this categorical framework, the structuring principles of the modelling approach are formalised in terms of the transformations that are allowed over objects (programs, specifications, behaviours, etc) to produce more complex objects. Morphisms capture the relationship that exists between two such objects. The operation of actually putting together objects can also be characterised in Category Theory in a universal way. As put forward by Goguen in the context of General Systems Theory, "given a category of widgets, the operation of putting a system of widgets together to form a super-widget corresponds to taking a colimit of the diagram of widgets that shows how to interconnect them" [Goguen and Ginali 78].
a:=F(g,a)]
The relationship between a program and a system of which it is a component is modelled through program morphisms. As already explained for signatures, morphisms embody the structuring principles of the software development approach being formalised. In the case of parallel program design languages, such structuring principles are usually cast in terms of superposition [Chandy and Misra 88, Bougé and Francez 88]. (The term "superimposition" is also used in the literature, namely in the works of N.Francez, with the same meaning. We shall use "superposition" just because it is shorter.) Hence, program morphisms are defined as signature morphisms satisfying a number of properties that capture the con-
In order to illustrate how colimits work, we consider first colimits of signature diagrams, in particular the simplest form of colimits: pushouts. Consider the following diagram:
– 3–
(P 1|| P2) ≡ P var a, b1, b2 : int do f1|| f2 : [p1∧p 2 → a,b 1,b 2 := 1,a+1,a–1] [] g 1 : [¬p 1 → b 1 := 1] [] g 2 : [¬p 2 → b 2 := 1]
θ ≡ Vint={a}; R=Ø; Γ={f} a œ a1 f œ f1
a œ a2 f œ f2
θ 1 ≡ V1 int={b 1 }; R1 ={a1 }; Γ1 ={f1, g1}
As already explained, because they are the image of the same action of the channel P, the two statements f 1 and f2 are "merged" into f1|| f2, meaning that the two components are re quired to synchronise in order to perform these actions. Because definition 6 requires that the guard of the image of each action implies the translation of the guard of the source action, and the colimit is a minimal combination of the component objects, the resulting ac tion is guarded by the conjunction of the guards of f 1 and f 2 (the minimal condition that is implied by p 1 and p2 is their conjunction). In this way, because program morphisms require the functionality of the actions to be preserved, the joint action f1|| f2 performs the union of the two multiple assignments (the union of two sets is the minimal set that contains them).
θ 2 ≡ V2 int={a2 ,b 2 }; R2 =Ø; Γ2 ={f2, g2}
This diagram expresses an interconnection between θ 1 and θ 2 via the "channel" θ . The morphisms connect a1 and a 2 via a , and f 1 and f 2 via f. The intuition is that we are interconnecting θ 1 and θ 2 by saying that the external attribute a1 of θ 1 is no other than the local attribute a2 of θ2, and that the two objects share an action, seen in θ1 as f 1 and in θ 2 as f 2. This intuition is materialised in the signature that results from the operation of interconnecting the two components. This operation corresponds to taking the colimit of this signature diagram. It returns the signature θ 1|| θ 2 ≡ var a, b1, b2 : int θ do f 1|| f2, g1, g2
Proposition 8: PROG is finitely cocomplete, i.e. it admits colimits of finite diagrams. ❚
together with the signature morphisms
3.2
Stepwise and incremental software development requires that software components be handled initially not at the level of the programs that implement them but at the level of their specifica tions . Specifications determine the properties that components are guaranteed to provide independently of the particular implementation chosen or of the environment in which they are placed. Specification morphisms again provide the means for specifying the interconnection between components and the rest of the system.
from θ1 and θ 2 to θ 1|| θ 2, respectively. Notice how the signature θ θ together with the corresponding morphisms to θ 1 and θ 2 capture the interconnection: actions f1 and f 2 are merged into the joint action f 1|| f2, and the attributes a 1 and a2 are identified. As intended, there are no external attributes in θ 1|| θ 2. θ
The colimit of a diagram returns the minimal object (signature in the case at hand) that can be related to the other objects of the diagram through morphisms, while respecting the interconnec tions defined in the diagram.
Following [Burstall and Goguen 77], specifications are best formalised as theory presentations in a given logic. The choice of logic is dictated by the nature of the properties in which we are interested. It is not surprising that focusing on different concepts results in the use of widely varying formalisms in which to deal with them. It is a faint hope, well illustrated by our experience with programming languages, that we will find a universally good single formalism for all occasions.
At the level of programs, this operation corresponds to a generalised parallel composition operator that allows for components to be interconnected through communication channels. An example, illustrated below, is the operation of superposing a regulator over a base program in the sense of [Francez and Forman 90]. Colimits in PROG are based on colimits in p-SIGN . Indeed, every diagram in PROG can be projected (through a forgetful functor) to a diagram in p-SIGN . The colimit of the signature diagram determines (mechanically) the signature and the morphisms of the colimit of the program diagram. The functionality of the resulting colimit program is fully determined by the signature colimit and the component programs. The proof and method for calculating program colimits is explained in [Fiadeiro and Maibaum 95].
In the case of reactive systems, computations provide us with a semantic domain in which we can reason about the properties of a system (safety and liveness) using a temporal logic [Manna and Pnueli 91]. In preparation for relating specifications and the programs as defined in the previous section, we shall illustrate the categorical account of specifications through a category of temporal theories as in [Fiadeiro and Maibaum 92].
a œ a2 f œ f2
Specifications are themselves built over signatures (the so called language of the specification). The signatures associated with a logic are described in terms of the different (grammatical) categories of non-logical symbols. In the case of the temporal logic that we have in mind, these consist just of pairs of sets, of non rigid (state-dependent) constants – corresponding to attributes, and of propositional symbols, respectively. See [Fiadeiro and Maibaum 92] for the full first-order version.
var a2, b2: int do f2: [p2→a2,b 2:=1,a2-1]
Definition 9: A temporal signature is a pair of sets τ=(Π,Λ). A morphism σ:( Π,Λ)→(Π', Λ') is a pair of total functions σ Π: Π→Π ', σΛ: Λ→Λ'. Temporal signatures constitute a category t-SIGN. ❚
The following example illustrates the method using the signature diagram studied above. Consider programs P=(θ ,∆), P1 =(θ 1,∆ 1), P2 =(θ 2,∆ 2) interconnected as follows: P ≡ read a : int do f : [ skip] a œ a1 f œ f1 P1 ≡
read a1: int; var b 1: int do f1: [p1→b1:=a 1+1]
[]
g 1: [¬p1→b1:=1]
Categories of specifications
P2 ≡ []
g 2: [¬p2→b2:=1]
The temporal language defined over a signature is as follows: Definition 10: Given a temporal signature τ =(Π,Λ), the language of terms over a sort s ∈S is as follows: t s ::= a | c | f(ts ,…,ts ) | Xt s
The pushout of this diagram gives us the program
1
– 4–
n
tion but are organised into modules (theories) that have a meaning in terms of the structure of the system – hence the use of morphisms for establishing interconnections through the language of these theories, something that cannot be achieved at the level of individual formulae.
for a ∈Πs, c∈Ω ,s and f∈Ω ,s. 1 n The language of temporal propositions is defined as follows: φ ::= (ts=st s) | p | (φ→φ) | (¬ φ) | beg | Xφ | φUφ for p∈Λ .
❚
The special operators are beg (denoting the initial state), X (X φ holds in a state when φ holds in the next state), and U (φUψ holds when ψ will hold sometime in the future and φ holds between now and then).
4
In order to be able to support the use of multiple formalisms during software development, we need ways of relating them. Having cast formalisms as categories, the obvious way of relating them is through functors.
Definition 11: A temporal theory is a pair ( τ,Φ) where Φ is a set of τ-propositions such that φ∈Φ for every Φ ‚ τ φ. A presentation of a theory (τ,Φ) is a pair ( τ,Ψ) such that Φ={ φ: Ψ‚τ φ}. ❚
By ‚τ we mean the usual consequence relation for linear, discrete temporal logic [e.g. Goldblatt 87].
Functors map the objects and morphisms of one category to corresponding objects and morphisms of another category. The fact that morphisms, and not only objects, get related is very important because it means that it is the structural properties of the two formalisms that are being related. In this section, we shall start by showing how a particularly useful functor can be defined between PROG and SPEC , and then abstract from this case the general categorical approach that we propose for handling multiple formalisms in software development.
That is to say, a theory over a signature is a set of propositions closed under consequence (it contains all of its theorems). A presentation of a theory is a set of propositions whose closure (set of theorems that can be derived) is that theory. Morphisms between theories (and presentations) also require a translation between the temporal languages: Definition 12: Given a signature morphism σ :τ→τ ': σ(t s) ::= σ(a) | c | f( σ(ts ),…,σ(ts )) | Xσ(ts) 1 n σ(φ) ::= ( σ(t s)=sσ(t s)) | σ(p) | (σ(φ)→σ(ϕ)) | ¬ σ(φ) | beg | Xσ(φ) | ( σ(φ)Uσ(ϕ))
Mapping between formalisms
4.1 ❚
From programs to specifications
In order to map programs to specifications, our experience so far tells us that we must consider their signatures first. Recalling the definitions of program and temporal signatures, we can see that there is a straightforward way of mapping program signatures to temporal signatures:
Definition/Proposition 13: A morphism of theory presenta tions σ: ( τ1,Φ 1)→(τ2,Φ 2) is a signature morphism σ: τ1 → τ2 such that Φ2‚τ σ(φ) for every φ∈Φ 1 . Theory presentations and their 2 morphisms constitute a category SPEC. ❚
Definition/Proposition 15: Define, for every program signature θ=(Α=V ⊕R,Γ), the temporal signature Spec (θ)=(Α,Γ). This map ping extends trivially to a functor Spec : p-SIGN → t-SIGN by mapping morphisms of program signatures to themselves. ❚
That is, a morphism of presentations is a signature morphism that defines a theorem preserving translation between the two theories. These are standard notions within institutions [Goguen and Burstall 92]. Institutions are an abstraction of certain structural properties of logics that allow us to organise the theories of the logics into categories, as illustrated above for temporal logic. Indeed, most of the logics that have been used for software specification have been shown to constitute institutions. Hence, the task of formalising specification formalisms as categories has been greatly facilitated, and there is considerable experience in discussing specification development in terms of categorical techniques [e.g. Sannella and Tarlecki 88].
That is to say, we map a program signature to a temporal signature by taking the attributes as the non-rigid constants and the actions as the atomic propositions. This is a good example of a mapping between two formalisms that are at different levels of abstraction: the information about which attributes are local and which are external is lost during the mapping process because the notion of temporal signature is not strong enough to capture it. Indeed, temporal logic is a formalism that can be associated with many other program design languages and, hence, its logical symbols do not commit the specifier to any particular encapsulation discipline.
For instance, it is a property of institutions that if the category of signatures admits colimits, so does the category of theory presentations. Hence,
This means that the "semantics" of the programming formalism will have to be translated, in part, to non-logical axioms in temporal logic. (Put in another way, conditions imposed on each program implicitly by the formalism of programs will have to be made explicit in the corresponding specification since the latter formalism does not impose the same 'discipline' of encapsulation.) Indeed, the mapping that really is of interest is the extension of Spec to a functor between PROG and SPEC .
Proposition 14: SPEC admits colimits of finite diagrams (i.e. is finitely cocomplete). ❚ Colimits of specification diagrams, just as for program diagrams, are computed over the colimit of the underlying signature diagram: a pushout of two morphisms µ 1 : ( θ,Φ)→(θ1,Φ 1 ) and µ2: ( θ,Φ)→(θ 2,Φ 2) is given by the specification (θ ', Φ') and mor phisms σ 1 and σ 2 such that θ', σ1 and σ 2 are a pushout of µ1 and µ2 as signature morphisms and Φ'=σ 1(Φ1)∪σ2(Φ2).
Definition 16: The functor Spec as defined earlier extends to a functor between PROG and SPEC by mapping every program (θ,∆) to the theory presentation Spec (θ,∆) whose signature is Spec (θ) and whose set of axioms Spec (∆) consists of: • the proposition (beg → I); • for every action g∈ Γ and every a∈ V, the proposition (g→Xa=F(g,a)); • for every g∈Γ , the proposition (g → Bg). ∨ g) ∨ Xa=a) • for every a ∈V, the proposition (( g∈D(a) ❚
That is, the set of axioms of the composite specification is the union of the translations of the axioms of the components. Because the union of sets of formulae has the same logical value as their conjunction, the categorical approach complies with the "composition as conjunction" idea put forward in [Abadi and Lamport 93] for parallel composition of reactive systems and also, in a related sense, in [Zave and Jackson 93]. However, we should stress that our approach is more "structured" in the sense that formulae are not being considered individually as units of construc-
– 5–
is important is that the functor can be associated with a map between different development levels.
These (non-logical) axioms do capture the semantics of the program: the first axiom establishes that I is an initialisation condition; the second set of axioms formalises the assignment – if g is about to occur, the next value of attribute a is the current value of F(g,a); the third establishes B g as a necessary condition for the oc currence of g; and the last axiom (the locality axiom) captures locality of attributes: if none of the actions of the program occurs, its local attributes remain invariant ([Fiadeiro and Maibaum 92]).
Definition 17: A realisation of a specification S is a pair < σ,P> such that P: PROG and σ is a specification morphism S→ Spec (P).❚ This notion of realisation is a generalisation of the satisfaction relation between programs and specifications. Traditionally, we say that a program P satisfies a specification S, P‚S, if every computation of P is a model of S. This notion of satisfaction requires that the program and the specification share the same "signature" and is equivalent to saying that S ⊆Spec (P). Realisations generalise this notion by allowing the program and the specification to be over different signatures. More concretely, the program is allowed to have features that are not relevant to the specification. Hence the morphism from S to Spec (P) corresponds to the way in which P realises S, i.e., intuitively, it records the design decisions that lead from S to P (seen as a design exercise carried out in SPEC ).
For instance, the programs P1 and P 2 introduced after definition 6 admit the following presentations
Spec (P 1) ≡
g1 → p g 1 → Xa=1 g 1 ∨ Xa=a
Spec (P 2) ≡
g 2 → p ∧q g 2 → Xa=1 g 2 → Xb=a+1 g 2 ∨ Xa=a
h 2 → ¬q h 2 → Xb=a+1 g 2 ∨ h2 ∨ Xb=b
Realisations can themselves be organised into a category: Definition/Proposition 18: Given a specification S, a morphism µ: → between realisations of S is a morphism µ:P →P' between the corresponding programs such that ❚ σ'= σ;Spec (µ). A category Real(S) is thus defined.
We have thus defined a mapping Spec from the objects of PROG to the objects of SPEC. In order to prove that this mapping extends to morphisms and, hence, defines a functor, it is sufficient to see that, given a program morphism σ: ( θ,∆)→(θ', ∆'), the conditions laid down in definition 6 for program morphisms together with the axioms of Spec (θ,∆) imply the axioms of Spec (θ', ∆').
The equation σ '=σ;Spec (µ) means that a realisation morphism is, essentially, a translation (or simulation) between the underlying programs that preserves the way the specification is being implemented, i.e. respects the design decisions. Hence, what we get in this way are categories of design decisions, which seems to be the right level of abstraction at which to discuss compositionality and reusability.
For instance, it is easy to see that the signature morphism , previously shown to be a program morphism between P1 and P 2, is also a morphism between the corresponding specifications.
Technically, the category Real(S) has a very particular structure – it is the comma-category (S ↓Spec ), for which a standard property is:
Notice that if a different notion of superposition (i.e. of program morphism) had been chosen, Spec might not be a functor, i.e. it might not map the program morphisms (of this new category) to specification morphisms. Indeed, the "semantics" of the programming language is more encoded in the morphisms than in the objects. For instance, if guards had been allowed to be weakened (i.e. if condition 4 had been omitted from definition 6), then Spec as defined above would not be a functor because the property (g→B g ) would not necessarily be preserved by program mor phisms. On the other hand, if condition 4 had been strengthened, e.g. by replacing the implication by an equivalence, Spec might have been more ambitious, for instance by abstracting liveness properties from programs. Hence, it is in the preservation of morphisms that the "correctness" of the functor as a mapping between formalisms lies.
4.2
Proposition 19: Every specification morphism σ:S→S' induces a functor Real(σ ): Real(S')→ Real (S) such that Real ( σ)= . ❚ This result has an intuitive interpretation in software development practice: it means that, given an extension S' of S (e.g. S' specifies a system of which S specifies a component), every realisation of S' gives rise, in a canonical way, to a realisation of S. The language of S provides the visibility on S' required to turn the design of S' into one for S. In the object oriented world, S' is a specialisation of S and, hence, it can be used in place of S, given the appropriate restriction on the visibility of features not in S. In other words, a realisation of an extension can be used wherever a realisation for the original specification is required. The dual is also true – every simulation of an implementation of S is itself an implementation of S:
Working with specifications and programs
Proposition 20: Given a realisation < σ,P> of a specification S and a program morphism µ:P→P', < σ; Spec (µ),P'> is itself a realisation of S. ❚
As motivated above, establishing a functor between two categories that correspond to two different formalisms is a strong structural property of the relationship between the two formalisms. It allows us in particular to work in a "heterogenous" software development environment in which abstractions of different formalisms can be used simultaneously.
This means that if S is the criterion for satisfaction of a software component, any program that implements S can be replaced by any other one that simulates it.
In order to illustrate how this can be achieved in the context of objects on different levels of abstraction, consider that two formalisms, corresponding to two different levels of development, have been presented as categories PROG and SPEC , and that a functor Spec: PROG → SPEC has been established between them. We are using the same notation as in the previous sections just for guiding intuitions; nothing of what we shall present is particular to the specific categories and functor previously presented, or to the fact that PROG is indeed a category of "executable" objects. What
What we now want is to know how programs and specifications can be used simultaneously, i.e. how, during development, we can work with a system that is being specified as an interconnection of simpler components, but where some of the components may actually correspond to programs that are already available whereas other components may be just specifications of software components to be developed or, even, abstractions of objects in the environment (human, mechanical, etc) with which the other components will interact.
– 6–
case in which one of the components, say S2, is already a program corresponds to the case where S2 is Spec (P 2). Hence, theorem 21 is another indication that the existence of a functor between two formalisms is a very strong property: it automatically leads to compositionality and reusability. This is so because functors are required to map program morphisms to specification morphisms, i.e. the properties that the functor assigns to a program must be preserved by (the translations of) program morphisms.
More concretely, consider a system specified as an interconnection of two components such that, for one of them, we have a program P 2 and, for the other one, we have only a specification S 1 . The diagram below specifies the required configuration, the specification Channel and the morphisms providing the interconnection between the components via their specifications. Channel ϕ
ϕ2
1
S1
Taking into account that morphisms characterise the structural properties of the domain, which in the case of software development formalisms corresponds to the degree of modularity that they support, our formalisation shows that compositionality is, indeed, a measure of the compatibility that exists between the modularity that is provided at the two levels. This complies with the way [Krueger 92] relates software reuse with abstraction, i.e. the relationship between two levels of development.
Spec (P2)
We want to know that if we later develop a program P1 for the specification S 1 and interconnect it with P2 as specified, the pushout at the program level (i.e. the composition of the programs) provides us with a realisation of the pushout of the specifications. A posi tive answer to this question means that the development of a sys tem can proceed incrementally, possibly by reusing existing soft ware components. Indeed, the result says that we do not need to wait for a program to be developed for S1 to know how the final, interconnected, system will behave. Part of the behaviour of the system is independent of the specific programs that are chosen to realise the specifications of its components, provided that they are inter connected as specified.
Hence, an advantage of the proposed categorical account of software development is that it allows us to concentrate our efforts on the functor, i.e. on choosing a relation between formalisms that is consistent with the way morphisms are used to structure systems.
4.3
Theorem 21 shows that the simple existence of a functor between the categories corresponding to two formalisms is already a powerful property. We now consider the situation in which a direct functor cannot be established between the two categories.
The answer to the question above is positive, and is a corollary of the following theorem: Theorem 21: Consider the SPEC diagram given by ϕ 1 and ϕ 2, interconnecting specifications S 1 and S2 via a channel S. Let , , be realisations of S, S 1 and S2, respec tively (i.e. η: S →Spec (P), η i: Si→ Spec (P i)), interconnected in a way that is consistent with the interconnection of the specifications, i.e. µ i: P →Pi are such that η ;Spec (µi)=ϕi;ηi. Then, there is a unique way in which the pushout program P' is a realisation of the pushout specification S', i.e. there is a unique η ':S' →Spec (P') s.t. βi;η'= ηi; Spec(σ i). β2
S2
As an example, consider that the requirements concerning the behaviour of a system component are expressed in a temporal language involving only actions. The choice of attributes can be seen to be already a design decision and, hence, there is no commitment at the requirements level about what structure to choose for representing the state of the component. For instance, consider the following specification of a producer using actions store and produce , where W is the weak until operator (p Wq means p will hold until q becomes true, if ever): Φ-p ≡ beg → (¬store) ∧ (produce ∨ (¬store) Wproduce) produce → (¬produce)Wstore store → (¬store)Wproduce produce → (¬store)
S' p.o.
ϕ2
β1
η2 ϕ1
S
η
η
SPEC
S1
η'
That is, a producer cannot do a store until it does the first pro duce ; each time it does a produce , it cannot do any other produce until it has done a store , and vice-versa for store ; and a producer cannot do both a produce and a store during the same state transi tion.
1
Spec(σ2)
Spec(P')
Spec(P2)
Spec(µ2)
This specification can be realised, for instance, by the following program: ∆-p ≡ var waiting : bool init waiting=false do store : [waiting=false → waiting:=true] [] produce : [waiting=true → waiting:=false]
Spec(σ1) Spec
Spec(P)
Spec(µ 1)
Spec(P1) σ2
P2
In order to prove that this is, indeed, the case, we just have to prove that the axioms Φ-p are theorems of Spec (∆-p).
P' p.o.
µ2
PROG P
Strictly speaking, Φ-p and Spec(∆-p) are not in the same logic: the logic for requirements specification does not allow for attributes. However, we can embed it in the logic corresponding to SPEC by considering that the set of attributes is empty.
σ1 µ1
Partial mappings
P1
More generally, we can assume that we have a category REQ of re quirement specifi cations together with a functor F : REQ→ SPEC. Hence, the rela tionship between programs (PROG) and requirements ( REQ ) is established via a middle category SPEC and two functors:
Indeed, theorem 21 states, in some generality, that whatever interconnection of specifications we have as a specification of a complex system, we can pick up arbitrary realisations of these specifications, interconnect them as specified, and obtain a composite program that is a realisation of the composite specification. The
– 7–
REQ
F
The advantage of the proposed categorical approach is that it provides us with a natural framework to relate not only the different kinds of objects (programs, specifications, abstractions of behaviours, etc) that are intrinsic to the variety of formalisms present during software development but also, and more importantly, the structuring principles that are implied by each formalism. Indeed, we saw how such structuring principles (superposition for the program category considered, and property preservation for the specification category considered) can be captured through the morphisms of a category, and how functors, as morphism-preserving mappings between categories, give an account of compositionality and reusability as properties of the relationship between the modularisation techniques available at two development levels, much in the spirit of approaching reuse through abstraction [Krueger 92].
SPEC Spec PROG
This is the more general situation (as compared to the programming and specification formalisms and their relationship illustrated earlier): because the two formalisms may be quite different, we may need a third (mediating ) formalism in which to relate them. That is, in a way, we go back to the idea of mapping the two formalisms to a common one, but in a local sense – the middle category does not correspond to a universal formalism but de pends only on the two particular formalisms that we are relat ing. In order to recover the properties discussed at the end of section 4.2, the notion of realisation given in definition 17 has to be generalised:
In order to generalise theorem 21 we need, however, to require that F preserves finite colimits. Indeed, starting with a pushout diagram in REQ, we need that its image in SPEC also be a pushout diagram so that we again find ourselves in the situation covered by theorem 21. This is not a very strong condition when F is a functor relating two logics (or institutions) as above. Indeed, it is a consequence of a much stronger property of maps of institutions [Meseguer 89].
The examples developed in the paper were chosen in order to illustrate how both programs and specifications can be used simultaneously and how reuse can be formalised in terms of a functorial relationship between two formalisms corresponding to two layers of abstraction. However, the theory also applies to the use of multiple formalisms at the same level of abstraction, supporting requirement specifications in different formalisms but over the same component. For instance, besides a temporal logic for expressing requirements on the evolution of a system, one could employ a deontic logic for expressing requirements on fault-tolerance or exception handling capabilities. In this respect, we intend to work out how the proposed categorical approach can be used to give formal support to the viewpoints approach proposed in [Finkelstein et al 92]. Moreover, we would like to explore more closely the methodological impact of the proposed techniques, possibly associated with their contribution to the definition of tools supporting the use of multiple formalisms in software development.
5
Acknowledgements
Definition 22: A realisation of a specification S:REQ is a pair such that P:PROG and σ is a specification morphism F(S) →Spec(P). ❚ Again, this means that realisations can be organised in a comma category ( F↓Spec ) from which the structural properties that we derived in section 4.2 can be generalised.
Concluding remarks
In this paper, we put forward the idea that Category Theory can be adopted as a uniform mathematical framework in which to map and relate formalisms used in software development, thus supporting a discipline of modular and incremental system development that promotes reuse.
We would like to thank Manny Lehman, Vic Stenning, Wlad Turski and Paulo Veloso for many enlightening discussions on software development and evolution, and the referees for some challenging comments.
This idea is supported by the results obtained in several areas of research, namely on the use of Category Theory for formalising process semantics of concurrent systems as in [Sassone et al 93]; the categorical approach to General Systems Theory developed by J.Goguen [e.g. Goguen and Ginali 78]; and the categorical approach to Specification Theory developed from institutions [Goguen and Burstall 92]. Moreover, functorial relationships have already been established inter and intra formalisms: [Sassone et al 93] use adjunctions to map between different process models, e.g. transition systems and synchronisation trees; in [Fiadeiro and Costa 95] we investigate properties of functors between categories of specifications and categories of process models, again via adjunctions; and several notions of morphism between institutions allow us to map between categories of theories of different logics.
References [Abadi and Lamport 93] M.Abadi and L.Lamport, "Composing Specifications", ACM TOPLAS 15(1), 1993, 73-132. [Back and Kurki-Suonio 88] R.Back and R.Kurki-Suonio, "Distributed Cooperation with Action Systems", ACM TOPLAS 10(4), 1988, 513-554. [Bougé and Francez 88] L.Bougé and N.Francez, "A Compositional Approach to Super imposition", in Proc. 15th ACM Symposium on Principles of Programming Languages", ACM Press 1988, 240-249.
We illustrated the universality of the approach, already suggested by the examples mentioned above, by using a category of temporal specifications in the line of [Fiadeiro and Maibaum 92], and a novel characterisation of a parallel program design language, COMMUNITY , in the style of IP [Francez and Forman 90], U NITY [Chandy and Misra 88] and Action Systems [Back and KurkiSuonio 88] that shows that pro grams also can be brought into the categorical realm in a natural way.
[Chandy and Misra 88] K.Chandy and J.Misra, Parallel Program Design - A Foundation , Addison-Wesley 1988. [Ehrig and Mahr 85] H.Ehrig and G.Mahr, Fundamentals of Algebraic Specifi cation 1: Equations and Initial Semantics , Springer-Verlag 1985
– 8–
[Fiadeiro and Costa 95] J.Fiadeiro and F.Costa, "Institutions for Behaviour Specification", in E.Astesiano, G.Reggio and A.Tarlecki (eds) Recent Trends in Data Type Specification , LNCS 906, Springer Verlag 1995.
[Moriconi and Qian 94] M.Moriconi nd X.Qian, "Correctness and Composition of Software Architectures", Proc. Second Symposium on the Foundations of Software Engineering, ACM Press 1994, 164-174.
[Fiadeiro and Maibaum 91] J.Fiadeiro and T.Maibaum, "Temporal Reasoning over Deontic Specifications", Journal of Logic and Computation 2(1), 1991, 357-395.
[Niskier et al 89] C.Niskier, T.Maibaum and D.Schwabe, "A Pluralistic Knowledge Based Approach to Software Specification" in C.Ghezzi and J.Mc Dermid (eds) 2nd European Software Engineering Conference, LNCS 387, Springer Verlag 1989, 411-423.
[Fiadeiro and Maibaum 92] J.Fiadeiro and T.Maibaum, "Temporal Theories as Modularisation Units for Concurrent System Specification", Formal Aspects of Computing 4(3), 1992, 239-272.
[Sannella and Tarlecki 88] D.Sannella and A.Tarlecki, "Building Specifications in an Arbitrary Institution", Information and Control 76, 1988, 165-210.
[Fiadeiro and Maibaum 95] J.Fiadeiro and T.Maibaum, Categorical Semantics of Parallel Program Design , Technical Report, FCUL and Imperial College, 1995.
[Sassone et al 93] V.Sassone, M.Nielsen and G.Winskel , "A Classification of Models for Concurrency", in E.Best (ed) CONCUR'93, LNCS 715, Springer-Verlag 1993, 82-96.
[Fiadeiro and Reichwein 92] J.Fiadeiro and G.Reichwein, "A Categorical Theory of Superposition", Technical Report, DMIST, 1992.
[Veloso et al 85] P.Veloso, T.Maibaum and M.Sadler, "Program Development and Theory Manipulation", Proc. Third International Workshop on Software Specification and Design, London, IEEE Computer Society Press 1985, 228-232.
[Finkelstein et al 92] A.Finkelstein, J.Kramer, B.Nuseibeh, L.Finkelstein and M.Goedicke, "Viewpoints: A Framework for Integrating Multiple Perspectives in Software Development", International Journal on Sofware Engineering and Knowledge Engineering 2(1), 1992, 31-57.
[Zave and Jackson 93] P.Zave and M.Jackson, "Conjunction as Composition", ACM TOSEM 2(4), 1993, 371-411.
[Francez and Forman 90] N.Francez and I.Forman, "Superimposition for Interacting Processes", in CONCUR'90, LNCS 458, Springer-Verlag 1990, 230-245.
Glossary
[Goguen 91] J.Goguen, "A Categorical Manifesto", Mathematical Structures in Computer Science 1(1), 1991, 49-67.
As
attributes that take value in sort s
Bg
guard of action g
[Goguen and Burstall 92] J.Goguen and R.Burstall, "Institutions: Abstract Model Theory for Specification and Programming", Journal of the ACM 39(1), 1992, 95-146.
F(g,a)
term whose value action g assigns to attribute a
Γ
set of actions of a program signature
I
initialisation condition of a program
[Goguen and Ginali 78] J.Goguen and S.Ginali, "A Categorical Approach to General Systems Theory", in G.Klir (ed) Applied General Systems Research , Plenum 1978, 257-270.
Λ
propositional symbols of a temporal signature
Πs
non-rigid constants of a temporal signature taking value in sort s
p-SIGN category of program signatures PROG category of programs
[Goldblatt 87] R.Goldblatt, Logics of Time and Computation, CSLI 1987. [Krueger 92] C.Krueger, "Software Reuse", ACM Computing Surveys 24(2), 1992, 131-183. [Lamport 89] L.Lamport, "A Simple Approach to Specifying Concurrent Systems", Communications of the ACM 32(1), 1989, 32-45. [Lehman et al 84] M.Lehman, V.Stenning and W.Turski, "Another Look at Software Design Methodology", Software Engineering Notes 9(2) 1984, 38-53.
θ
program signature ( Α=V ⊕R,Γ )
REQ
category of requirement specifications
Rs
external (read) attributes that take value in sort s
S
set of sorts
SPEC Spec
category of program specifications
τ
temporal signature (Π,Λ)
functor PROG → SPEC
t-SIGN category of temporal signatures
[Manna and Pnueli 91] Z.Manna and A.Pnueli, The Temporal Logic of Reactive and Concurrent Systems, Springer-Verlag 1991. [Meseguer 89] J.Meseguer, "General Logics", in H.-D.Ebbinghaus et al (eds) Logic Colloquium 87, North-Holland 1989.
– 9–
Vs
local attributes (program variables) taking value in sort s
Ωu,s
data operations taking arguments in u∈ S* and value in s