Composable Objects with Multiple Views and Layering - trese ...
Composable Objects with Multiple Views and Layering - trese ...
Composable Objects with Multiple Views and Layering - trese ...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Universiteit Twente<br />
De ondernemende<br />
universiteit<br />
<strong>Composable</strong> <strong>Objects</strong><br />
<strong>with</strong> <strong>Multiple</strong> <strong>Views</strong><br />
<strong>and</strong> <strong>Layering</strong><br />
Graduation Committee<br />
Dr. ir. M. Aksit<br />
Dr. ir. K.G. van den Berg<br />
Dr. P.M. van den Broek<br />
Ing. R.R. van de Stadt<br />
S.G. de Bruijn, March 1998<br />
MSc. Thesis at the Department of Computer Science<br />
University of Twente, Department of Computer Science, SETI, TRESE
Abstract<br />
When software systems were becoming too complex, people developed the<br />
object-oriented model. It enabled them to build pieces of software more or less<br />
independent from each other. This resulted in better underst<strong>and</strong>able systems<br />
which were easier to maintain.<br />
The use of the object-oriented model has solved a lot of architectural<br />
problems, but the experience in using the model drives us further: We now<br />
want to enrich our software models <strong>with</strong> more problem-domain properties, by<br />
making these properties explicit. This enables us to represent these properties<br />
more precisely, making software systems even better underst<strong>and</strong>able <strong>and</strong><br />
maintainable.<br />
Introducing problem-domain properties in a software model should not<br />
interfere <strong>with</strong> the already existing elements of this model. This is often not true<br />
however. In this thesis, we presenttwo modelling issues. We give our de nition of<br />
the issues, <strong>and</strong> try to discuss them using a traditional object-oriented language.<br />
In doing so, we encounter a lot of problems, <strong>and</strong> nally must conclude that<br />
expressing the presented modelling issues in a language like C ++ cannot be<br />
done in a fully satisfactory way.<br />
Next to a traditional object-oriented language, we also use the modelling<br />
issues in a next-generation object-oriented language called Sina. This language<br />
is based on an enhanced object-oriented model, basically enabling the software<br />
engineer to h<strong>and</strong>le <strong>and</strong> manipulate message calls between objects explicitly. We<br />
will see that <strong>with</strong> the Composition Filters Object Model, as the enhanced model<br />
is called, it is perfectly possible to express the presented modelling issues in a<br />
natural way, while preserving all the properties of the object-oriented model.<br />
Next to using modelling issues in software systems, it is also important<br />
to record them for later reuse. A Software Design Pattern has proved to<br />
be an e cient medium for the propagation of modelling knowledge. When we<br />
try to present our modelling issues as design patterns however, we discover<br />
that Gamma, Helm, Johnson <strong>and</strong> Vlissides's (1995) pattern scheme is not rich<br />
enough to express our modelling issues. In this thesis, we extend this Design<br />
Pattern notation, <strong>and</strong> represent our design issues using this extended notation.
Samenvatting<br />
Toen softwaresystemen te complex werden, ontstond het object-georienteerde<br />
model. Dit model stelde de softwareontwikkelaars in staat om softwaresystemen<br />
te bouwen die bestonden uit een aantal min of meer onafhankelijke bouwstenen.<br />
Deze opzet resulteerde in systemen die beter te begrijpen en te onderhouden<br />
waren.<br />
Door het gebruik van object-georienteerde technieken zijn veel problemen<br />
in de softwarebouw met betrekking tot de interne architectuur opgelost. Nu<br />
men daar wat meer ervaring mee heeft, is het gewenst om meer voordeel uit<br />
de inzet van deze technieken te halen. We willen de eigenschappen van het<br />
probleemdomein van de software explicieter gaan modelleren. Dit geeft meer<br />
inzicht in de materie dan de \normale" impliciete modellering. Tevens leidt dit<br />
tot beter inzichtelijke softwaresystemen die ook beter te onderhouden zijn.<br />
Wanneer we het probleemdomein expliciet gaan modelleren, mag dit uiteraard<br />
niet in strijd zijn met reeds aanwezige softwaremodellen. Vaak blijkt<br />
echter dat dit juist wel het geval is. In dit afstudeerverslag presenteren we twee<br />
modelleringskwesties. We geven de door ons gebruikte de nities en proberen<br />
de modellen in een normale object-georienteerde taal te realiseren. We komen<br />
hierbij veel problemen tegen die niet eenvoudig oplosbaar blijken en uiteindelijk<br />
moeten we tot de conclusie komen dat het niet mogelijk is om probleemdomeinen<br />
op een acceptabele wijze expliciet in een object-georienteerde taal als C ++<br />
te realiseren.<br />
Naast realisatie in een normale object-georienteerde taal, bouwen we ook<br />
modellen voor dezelfde modelleringskwesties in de moderne object-georienteerde<br />
taal Sina. Deze taal is gebaseerd op een verbeterd objectmodel dat in principe<br />
de software engineer de middelen geeft om methode-aanroepen expliciet af te<br />
h<strong>and</strong>elen en ze te manipuleren. We zullen laten zien dat met dit Compositie<br />
Filters Object Model de gepresenteerde modelleringskwesties uitstekend zijn<br />
te realiseren, zonder de oorspronkelijke voordelen van het object-georienteerde<br />
model te verliezen.<br />
Wanneer modelleringskwesties goed zijn uitgewerkt in afgebakende modellen,<br />
zijn ze in principe geschikt om later opnieuw te worden ingezet in een<br />
<strong>and</strong>er softwaresysteem. Software Design Patterns blijken tot op heden een e ectieve<br />
notatie voor dergelijke modelleringskennis en -ervaring te zijn. De notatie<br />
van (Gamma et al. 1995) is geent op het normale object model en blijkt tekort<br />
te schieten wanneer we onze oplossingen uitgedrukt in het Compositie<br />
Filters Object Model willen presenteren. Daarom geven we in dit verslag ook<br />
een aanpassing van de Design Pattern notatie en drukken hierin de door ons<br />
aangedragen modellen uit.
Preface<br />
You would not be reading this if I had not received the unlimited patience that<br />
my family, my friends, my graduation committee <strong>and</strong>, last but not least, my<br />
employer gave me.<br />
Thank you all.<br />
S.G. de Bruijn<br />
March 1998, Laren{NH
Contents<br />
1 Introduction 1<br />
1.1 Project boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . 2<br />
1.2 Structure of this thesis . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
2 Background <strong>and</strong> related work 7<br />
2.1 Object models . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
2.1.1 Conventional Object Model . . . . . . . . . . . . . . . . . 7<br />
2.1.2 Composition Filters Object Model . . . . . . . . . . . . . 8<br />
2.2 Design Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
2.3 Position of this work in the TRESE project . . . . . . . . . . . . 10<br />
3 Modelling Issue: <strong>Multiple</strong> <strong>Views</strong> 11<br />
3.1 Modelling <strong>Multiple</strong> <strong>Views</strong> . . . . . . . . . . . . . . . . . . . . . . 11<br />
3.1.1 What is a View? . . . . . . . . . . . . . . . . . . . . . . . 12<br />
3.1.2 Conceptual View Model . . . . . . . . . . . . . . . . . . . 14<br />
3.1.3 Scenario of Changes . . . . . . . . . . . . . . . . . . . . . 17<br />
3.2 C ++ Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />
3.2.1 Simple Mail System . . . . . . . . . . . . . . . . . . . . . 22<br />
3.2.2 Add <strong>Views</strong>: UserSystemView Mail System . . . . . . . . . 24<br />
3.2.3 View Partitioning: OriginatorReceiverView Mail System . 26<br />
3.2.4 View Extension: Group Mail System . . . . . . . . . . . . 28<br />
3.2.5 Dynamic Behaviour Extension: Secure Mail System . . . 30<br />
3.2.6 Static Meta Behaviour Extension: Warning2 Mail System 31<br />
3.2.7 View Composition: Protected Mail System . . . . . . . . 34<br />
3.3 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />
4 Modelling Issue: <strong>Layering</strong> 39<br />
4.1 Modelling Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />
4.1.1 What is <strong>Layering</strong>? . . . . . . . . . . . . . . . . . . . . . . 39<br />
4.1.2 Conceptual <strong>Layering</strong> Model . . . . . . . . . . . . . . . . . 42<br />
4.1.3 Scenario of Changes . . . . . . . . . . . . . . . . . . . . . 49<br />
4.2 C ++ implementation . . . . . . . . . . . . . . . . . . . . . . . . . 51<br />
4.2.1 Add Methods: Heading Mail System . . . . . . . . . . . . 51<br />
4.2.2 Rede ne Methods: Attachment Mail System . . . . . . . . 53<br />
i
ii Contents<br />
4.2.3 Extend Methods: ReadNoti cation Mail System . . . . . 53<br />
4.2.4 Add Object-Orthogonal Behaviour: History Mail System . 55<br />
4.2.5 Dynamic <strong>Layering</strong>: Dynamic Mail System . . . . . . . . . 56<br />
4.3 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57<br />
5 Composition Filters Solutions for the Modelling Issues 61<br />
5.1 The Sina Language . . . . . . . . . . . . . . . . . . . . . . . . . . 61<br />
5.2 <strong>Multiple</strong> <strong>Views</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />
5.2.1 Simple Mail System . . . . . . . . . . . . . . . . . . . . . 62<br />
5.2.2 Add <strong>Views</strong>: UserSystemView Mail System . . . . . . . . . 62<br />
5.2.3 View Partitioning: OriginatorReceiverView Mail System . 64<br />
5.2.4 View Extension: Group Mail System . . . . . . . . . . . . 67<br />
5.2.5 Dynamic Behaviour Extension: Secure Mail System . . . 68<br />
5.2.6 Static Meta Behaviour Extension: Warning2 Mail System 68<br />
5.2.7 View Composition: Protected Mail System . . . . . . . . 68<br />
5.3 <strong>Layering</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69<br />
5.3.1 Add Methods: Heading Mail System . . . . . . . . . . . . 70<br />
5.3.2 Rede ne Methods: Attachment Mail System . . . . . . . . 70<br />
5.3.3 Extend Methods: ReadNoti cation Mail System . . . . . 70<br />
5.3.4 Add Object-Orthogonal Behaviour: History Mail System . 71<br />
5.3.5 Dynamic <strong>Layering</strong>: Dynamic Mail System . . . . . . . . . 72<br />
5.4 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72<br />
6 <strong>Composable</strong> Models Presented as Design Patterns 75<br />
6.1 Enabling Design Patterns to Present <strong>Composable</strong> Models . . . . 75<br />
6.2 Design Pattern: <strong>Composable</strong> <strong>Multiple</strong> Object <strong>Views</strong> . . . . . . . 80<br />
6.3 Design Pattern: <strong>Composable</strong> Object <strong>Layering</strong> . . . . . . . . . . . 85<br />
6.4 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92<br />
7 Conclusions <strong>and</strong> Future Work 93<br />
7.1 Comparison of the C ++ <strong>and</strong> the Sina implementations . . . . . . 93<br />
7.1.1 <strong>Multiple</strong> <strong>Views</strong> . . . . . . . . . . . . . . . . . . . . . . . . 93<br />
7.1.2 <strong>Layering</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />
7.2 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95<br />
7.3 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96<br />
A C++ Implementation of <strong>Multiple</strong> <strong>Views</strong> 99<br />
A.1 Simple Mail System . . . . . . . . . . . . . . . . . . . . . . . . . 99<br />
A.2 UserSystemView Mail System . . . . . . . . . . . . . . . . . . . . 104<br />
A.3 OriginatorReceiverView Mail System . . . . . . . . . . . . . . . . 113<br />
A.4 Group Mail System . . . . . . . . . . . . . . . . . . . . . . . . . . 116<br />
A.5 Secure Mail System . . . . . . . . . . . . . . . . . . . . . . . . . . 118<br />
A.6 Warning2 Mail System . . . . . . . . . . . . . . . . . . . . . . . . 121<br />
A.7 Protected Mail System . . . . . . . . . . . . . . . . . . . . . . . . 124
Contents iii<br />
B Sina Implementation of <strong>Multiple</strong> <strong>Views</strong> 129<br />
B.1 Simple Mail System . . . . . . . . . . . . . . . . . . . . . . . . . 129<br />
B.2 UserSystemView Mail System . . . . . . . . . . . . . . . . . . . . 134<br />
B.3 OriginatorReceiverView Mail System . . . . . . . . . . . . . . . . 135<br />
B.4 Group Mail System . . . . . . . . . . . . . . . . . . . . . . . . . . 137<br />
B.5 Secure Mail System . . . . . . . . . . . . . . . . . . . . . . . . . . 139<br />
B.6 Warning2 Mail System . . . . . . . . . . . . . . . . . . . . . . . . 141<br />
B.7 Protected Mail System . . . . . . . . . . . . . . . . . . . . . . . . 143<br />
C C++ Implementation of <strong>Layering</strong> 147<br />
C.1 Heading Mail System . . . . . . . . . . . . . . . . . . . . . . . . . 147<br />
C.2 Attachment Mail System . . . . . . . . . . . . . . . . . . . . . . . 149<br />
C.3 ReadNoti cation Mail System . . . . . . . . . . . . . . . . . . . . 151<br />
C.4 History Mail System . . . . . . . . . . . . . . . . . . . . . . . . . 153<br />
C.5 Dynamic Mail System . . . . . . . . . . . . . . . . . . . . . . . . 159<br />
D Sina Implementation of <strong>Layering</strong> 171<br />
D.1 Heading Mail System . . . . . . . . . . . . . . . . . . . . . . . . . 171<br />
D.2 Attachment Mail System . . . . . . . . . . . . . . . . . . . . . . . 172<br />
D.3 ReadNoti cation Mail System . . . . . . . . . . . . . . . . . . . . 175<br />
D.4 History Mail System . . . . . . . . . . . . . . . . . . . . . . . . . 178<br />
D.5 Dynamic Mail System . . . . . . . . . . . . . . . . . . . . . . . . 180<br />
Bibliography 185
iv Contents
List of Figures<br />
2.1 Conventional Object Model . . . . . . . . . . . . . . . . . . . . . 8<br />
2.2 Composition Filters Object Model . . . . . . . . . . . . . . . . . 8<br />
3.1 <strong>Multiple</strong> <strong>Views</strong> in an object-oriented environment . . . . . . . . . 13<br />
3.2 Conceptual Model of <strong>Multiple</strong> <strong>Views</strong> . . . . . . . . . . . . . . . . 14<br />
3.3 Many-to-many relationship between methods M o <strong>and</strong> views V o . 16<br />
3.4 Set Operations on <strong>Views</strong> . . . . . . . . . . . . . . . . . . . . . . . 17<br />
3.5 <strong>Multiple</strong> <strong>Views</strong> Scenario . . . . . . . . . . . . . . . . . . . . . . . 21<br />
3.6 Object Interaction Diagram for the Mail System . . . . . . . . . 23<br />
3.7 Adding <strong>Views</strong> in C ++ . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
3.8 Partitioning <strong>Views</strong> in C ++ . . . . . . . . . . . . . . . . . . . . . . 29<br />
3.9 Dynamic Behaviour Extension in C ++ . . . . . . . . . . . . . . . 32<br />
3.10 Static Meta Behaviour Extension in C ++ . . . . . . . . . . . . . . 33<br />
3.11 View Composition in C ++ . . . . . . . . . . . . . . . . . . . . . . 35<br />
4.1 Object Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40<br />
4.2 Role playing modelled <strong>with</strong> a layer . . . . . . . . . . . . . . . . . 40<br />
4.3 The Unix operating system divided into several layers . . . . . . 41<br />
4.4 Layered Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />
4.5 Conceptual Model of <strong>Layering</strong> . . . . . . . . . . . . . . . . . . . . 43<br />
4.6 Static layering generates complex class structures . . . . . . . . . 46<br />
4.7 Dynamic layering keeps class structures simple . . . . . . . . . . 47<br />
4.8 Separate Behaviour from Control: History recording of objects<br />
Obj1 <strong>and</strong> Obj2 is controlled by anOperator . . . . . . . . . . . 48<br />
4.9 <strong>Multiple</strong> Private Properties assigned to one single object . . . . . 49<br />
4.10 <strong>Layering</strong> Scenario . . . . . . . . . . . . . . . . . . . . . . . . . . . 51<br />
4.11 Never access \lower level" structures directly . . . . . . . . . . . 52<br />
4.12 Rede ned methods basically extending functionality must call<br />
the original method, <strong>and</strong> often are conditional in their extension 54<br />
4.13 Separate Mail Read <strong>and</strong> Send ReadNoti cation functionalities . . 55<br />
4.14 Every method has to be rede ned to implement history information<br />
recording . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56<br />
4.15 C ++ example of one simple function in a Decorator pattern . . 58<br />
5.1 Deadlock ofsend message in the MailH<strong>and</strong>ler . . . . . . . . . . . 63<br />
v
vi List of Figures<br />
5.2 Implementation of method-view coupling in Sina . . . . . . . . . 65<br />
5.3 Method View Composition . . . . . . . . . . . . . . . . . . . . . 67<br />
5.4 View Extension only rede nes the view . . . . . . . . . . . . . . . 67<br />
5.5 Conditionally redirect messages to specialized versions . . . . . . 68<br />
5.6 Coupling meta behaviour to an object . . . . . . . . . . . . . . . 69<br />
5.7 Composing views is extremely simple using Composition Filters . 69<br />
5.8 Code example of conditional method skipping . . . . . . . . . . . 71<br />
5.9 Orthogonal behaviour is very simple to add to an existing class . 71<br />
5.10 Structure of an object <strong>with</strong> dynamic layering property . . . . . . 72<br />
5.11 Composing functionalities goes rather well using Composition<br />
Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73<br />
6.1 Graphical message notations from the message's viewpoint. A<br />
message is either not ltered at all, or passes one or more lters<br />
which inspect <strong>and</strong>/or manipulate its runtime behaviour. . . . . . 77<br />
6.2 Filter Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78<br />
6.3 An example mail system . . . . . . . . . . . . . . . . . . . . . . . 80<br />
6.4 The structure of the <strong>Multiple</strong> <strong>Views</strong> pattern . . . . . . . . . . . . 81<br />
6.5 Code template for the <strong>Multiple</strong> <strong>Views</strong> Pattern . . . . . . . . . . . 83<br />
6.6 Interface de nition of the Mail class . . . . . . . . . . . . . . . . 83<br />
6.7 Implementation extract of the Mail class . . . . . . . . . . . . . 84<br />
6.8 An example mail system <strong>with</strong> history recording . . . . . . . . . . 85<br />
6.9 Mail system <strong>with</strong> a history recorder <strong>and</strong> a message decoder . . . 86<br />
6.10 Message Diagram of the Basic Dynamic Layer . . . . . . . . . . . 87<br />
6.11 Message Diagram of the <strong>Composable</strong> Object Layer Pattern . . . 87<br />
6.12 How tomake a generic property a dynamic layer . . . . . . . . . 90<br />
6.13 How tomake a normal class a dynamic layered class . . . . . . . 90<br />
6.14 How to use a dynamic layered object . . . . . . . . . . . . . . . . 91
Chapter 1<br />
Introduction<br />
This thesis is about objects. <strong>Objects</strong> have proven to have a positive e ect on<br />
the underst<strong>and</strong>ability <strong>and</strong> maintainability of software. This is the result of specifying<br />
individual components of a software architecture <strong>with</strong> a well-de ned interface,<br />
in such away that these components can be used elsewhere easily.<br />
Sometimes, it is not so easy to de ne these components correctly, <strong>and</strong><br />
when some modelling aspects are used, this will eventually result in implementations<br />
that can no longer be easily adapted or integrated <strong>with</strong> existing<br />
components.<br />
In this thesis, we focus on two di erent modelling issues, <strong>and</strong> try to<br />
model them in C ++, which is assumed to be familiar to the reader. Because we<br />
expect to encounter problems when using C ++, we also will use the language<br />
Sina for modelling purposes. We then are able to compare the two <strong>with</strong> respect<br />
to expressive power. The Sina language was developed at TRESE, <strong>and</strong> is based<br />
on the Composition Filters Object Model, which isintroduced in Section 2.1.<br />
This thesis is also about patterns. The working community is realising that<br />
experience is hard to catch. Every person entering the working community must<br />
learn all the ins <strong>and</strong> outs of his or her discipline. Unfortunately, this takes a<br />
considerable amount of time. Further, knowledge is present, but has not been<br />
written down.<br />
Christopher Alex<strong>and</strong>er was one of the rst to write down his experiences.<br />
In Alex<strong>and</strong>er (1977), he described the ins <strong>and</strong> outs of architecture. People starting<br />
to work in this area can speed up their knowledge acquisition signi cantly<br />
by using his work.<br />
The software industry is busy trying to achieve the same <strong>with</strong> Object Oriented<br />
Software Design Patterns. Gamma et al. (1995) wrote down how software<br />
objects can be arranged <strong>and</strong> built to achieve certain behaviour <strong>and</strong> characteristics.<br />
Section 2.2 gives a more complete introduction to this material.<br />
In this thesis, we will present two modelling issues for which the Composition<br />
Filters Object Model, the model on which the Sina language is based, will<br />
1
2 Chapter 1. Introduction<br />
provide adequate implementations. Although the Composition Filters Object<br />
Model solves a lot of problems, they are not all presented in a uniform format.<br />
Further, the current representation format of these solutions prevents the<br />
work that is done in the TRESE group from being spread enough. This is partly<br />
because the TRESE work is relatively theoretical, <strong>and</strong> \normal" developers<br />
can't clearly see the advantages that the Composition Filters Object Model<br />
has above the Conventional Object Model, on which languages like C ++ <strong>and</strong><br />
Smalltalk are based.<br />
To make our work accessible, we will present the addressed modelling<br />
issues in this thesis not only <strong>with</strong> examples, but also as Software Design Patterns.<br />
To be able to do this, we rst will have to look at the currently most used Design<br />
Pattern Denotation, <strong>and</strong> how problem solutions using the Composition Filters<br />
Object Model will t in.<br />
1.1 Project boundaries<br />
Terminology<br />
In this thesis several terms are used. These are explained here to avoid misunderst<strong>and</strong>ings.<br />
The word model is the most confusing word in this thesis. We identify<br />
three di erent meanings, which are explained here:<br />
Object model The object model is the foundations on which objects are constructed.<br />
Elements of an object model are for example classes, objects,<br />
attributes <strong>and</strong> methods. Properties are for example inheritance <strong>and</strong> encapsulation.<br />
There are di erent object models. The best known are the models of C ++<br />
<strong>and</strong> Smalltalk. These models are alike, but di er for example in metamodelling.<br />
Classes are implicit in C ++, while they are explicitly available<br />
in Smalltalk.<br />
Problem domain model Software engineering concepts, like distribution or<br />
views for example, are de ned by so-called conceptual models, which<br />
relate participants <strong>and</strong> other elements of the concepts to eachother. We<br />
will call this kind of model a problem domain model in this thesis. This<br />
is the model of the term \modelling issue".<br />
Software model The software model is also often referred to as the application<br />
model. By software model we mean the model that is constructed<br />
for the individual objects for the application itself. In a mail system for<br />
example, the MailMessage object is a part of the software model of the<br />
mail system.<br />
We will use these speci c terms instead of the generic term \model" as much<br />
as possible.
1.1. Project boundaries 3<br />
Some other terms that we use are:<br />
Conventional Object Model This is the \well-known" object model that is<br />
normally used.<br />
Composition Filters Object Model This is the object model that is used<br />
to show solutions to modelling problems. It is an enhancement of the<br />
Conventional Object Model, <strong>and</strong> extends the message sending semantics.<br />
Method The implementation of certain behaviour of an object.<br />
Message The \call" of a method of an object.<br />
Message sender The object that sends a message.<br />
Message receiver The object to which the message sender initially sent the<br />
message to.<br />
Access control The ability to block one or more messages, depending on internal<br />
state information, or the sender's class or object identity.<br />
Static vs. dynamic binding Static binding means compile-time binding of<br />
behaviour. Dynamic binding means runtime binding of behaviour.<br />
Message context This is all relevant context information of a message. This<br />
includes the sender, the receiver <strong>and</strong> the method that is called.<br />
Languages<br />
The examples will be worked out in two di erent implementation languages.<br />
These are C ++ <strong>and</strong> Sina. These languages are chosen for various reasons:<br />
C++ This language is hybrid. The origins are in the C language, to which OO<br />
extensions are added. When used well, one can get a reasonable implementation<br />
of an OO system. It scores high when it comes to speed, <strong>with</strong><br />
the cost of not having context information of message calls. The language<br />
supports static multiple inheritance <strong>and</strong> uses the Conventional Object<br />
Model. Access control is addressed in a limited way, <strong>and</strong> it is static. Meta<br />
information about objects, classes <strong>and</strong> messages is completely absent.<br />
Sina This is the only language known that supports the Composition Filters<br />
Object Model. 1 Sina does not support inheritance at all as a language<br />
construct (as well as the Composition Filters Object Model does not<br />
support this semantics as an explicit feature), but it is capable of implementing<br />
(even dynamic) multiple inheritance semantics. Access control<br />
is completely in the h<strong>and</strong>s of the designer, is dynamic <strong>and</strong> can be dependent<br />
of the context of the message.<br />
Although we do not work out the implementations in Smalltalk, we will sometimes<br />
use Smalltalk examples for illustrative purposes.<br />
1. Well, there are implementations of lters in Smalltalk (Mordhorst <strong>and</strong> van Dijk 1996) <strong>and</strong><br />
C ++ (Gl<strong>and</strong>rup 1995). An implementation in Java is being examined.
4 Chapter 1. Introduction<br />
1.2 Structure of this thesis<br />
In Chapter 2, a quick introduction is given about object orientation, design<br />
patterns, the Composition Filters Object Model <strong>and</strong> its relation <strong>with</strong> the Conventional<br />
Object Model.<br />
Chapter 3 <strong>and</strong> Chapter 4 both discuss a certain modelling issue in detail.<br />
Both chapters show a model, the various adaptations one can make to the model,<br />
<strong>and</strong> how it can be implemented in a conventional object oriented language (C ++<br />
in this case, see Section 1.1). Various (dis)advantages of the implementations<br />
are also discussed. Implementations of the examples are included in appendices<br />
A <strong>and</strong> C.<br />
The implementation of the examples from Chapters 3 <strong>and</strong> 4 in Sina<br />
is discussed in Chapter 5. It shows the advantage of the Composition Filters<br />
Object Model over the Conventional Object Model of a language like C ++.<br />
Appendices B <strong>and</strong> D show the full implementations.<br />
The solutions given in Chapter 5 are used as a basis for constructing an<br />
extension to Gamma et al.'s (1995) design pattern denotation, that is capable<br />
of expressing solutions in the Composition Filters Object Model. This format<br />
is described in Chapter 6. To show that the composable design pattern format<br />
works, we provide patterns for <strong>Multiple</strong> <strong>Views</strong> <strong>and</strong> Dynamic <strong>Layering</strong>.<br />
Chapter 7 summarises the conclusions of this work, <strong>and</strong> gives suggestions<br />
about future research activities.<br />
How to read this thesis<br />
When the reader is unfamiliar <strong>with</strong> one or more of the terms Object Orientation,<br />
Design Patterns <strong>and</strong> the Composition Filters Object Model, it is recommended<br />
to read the appropriate section(s) of Chapter 2 rst.<br />
Both Chapters 3 <strong>and</strong> 4 introduce <strong>and</strong> explain a speci c problem in object<br />
oriented modelling. When the reader is interested in these problems, it is<br />
recommended to read the chapters completely. Otherwise, certain sections can<br />
be skipped. The layout of both chapters is the same, <strong>and</strong> is brie y described<br />
here.<br />
First, in Sections 3.1.1 <strong>and</strong> 4.1.1, an intuitive de nition will be given<br />
of the problem at h<strong>and</strong>. When the reader is familiar <strong>with</strong> the material, these<br />
sections can be skipped. Sections 3.1.2 <strong>and</strong> 4.1.2 describe a conceptual model,<br />
which re ects our ideas about the subject, <strong>and</strong> on which the scenarios <strong>and</strong> the<br />
examples are based. When Chapter 5 is read also, it is strongly recommended<br />
to read these sections, also when the subject is familiar. Also interesting in that<br />
case are Sections 3.1.3 <strong>and</strong> 4.1.3, which describe the scenarios that are used<br />
in the examples in more detail. The example workouts (Sections 3.2 <strong>and</strong> 4.2)<br />
<strong>and</strong> the forthcoming conclusions in Sections 3.3 <strong>and</strong> 4.3 are only interesting to<br />
readers who want to know which problems can arise when using a language like<br />
C ++. People only interested in Sina solutions can jump directly to Chapter 5.<br />
Chapter 6 addresses the part about Software Design Patterns, <strong>and</strong> how
1.2. Structure of this thesis 5<br />
implementations using the Composition Filters Object Model can be expressed<br />
as Design Patterns. Basically, Chapter 6 can be read on its own, but it does assume<br />
some familiarity about the Mail System, the example that is used throughout<br />
this thesis, <strong>and</strong> the modelling issues addressed in Chapters 3 <strong>and</strong> 4.
6 Chapter 1. Introduction
Chapter 2<br />
Background <strong>and</strong> related work<br />
Object-orientation has proven to have a positive e ect on the development of<br />
software. The complexity of systems can be reduced by reusing several parts<br />
of other systems that have been built before. Also, the exibility is improved<br />
by separating the interface from the implementation. This enables the software<br />
engineers to `plug in' new or changed components <strong>with</strong>out changing other parts<br />
of the system, as long as the interface of these new parts conform to a certain<br />
pre-de ned interface. There are several object models from whichwe will use two<br />
di erent types. Section 2.1 explains the di erences between the Conventional<br />
Object Model <strong>and</strong> the Composition Filters Object Model.<br />
Software Quality is improved by reusing parts that have proven to be<br />
correct. If it is not possible to reuse existing object code, it still is very usefull<br />
to reuse modelling knowledge. In Section 2.2 Software Design Patterns are<br />
introduced, which have proven to be an e ective medium for distributing this<br />
knowledge.<br />
Section 2.3 nally positions this work in the TRESE project.<br />
2.1 Object models<br />
In this section, we will describe the two Object Models that we use in this thesis.<br />
These are not full introductions to the models, but merely simple descriptions<br />
which show the fundamental di erences between them. For a full description,<br />
we refer to Bergmans (1994, Chapter 2).<br />
2.1.1 Conventional Object Model<br />
The conventional object model describes objects as a collection of instance<br />
variables, methods <strong>and</strong> parent classes. The number of allowed parent classes is<br />
language dependent; some languages allow only one parent class (single inheritance)<br />
<strong>and</strong> others allow more than one parent class (multiple inheritance). A<br />
more or less st<strong>and</strong>ard picture for the Conventional Object Model is displayed<br />
in Figure 2.1.<br />
The gure shows an Object, associated <strong>with</strong> one Parent object. The<br />
Parent object is painted dotted, because it is not a real object (at least not in a<br />
7
8 Chapter 2. Background <strong>and</strong> related work<br />
00 11<br />
00 11<br />
objMethod<br />
Object Parent<br />
000 111<br />
000 111<br />
parMethod<br />
Figure 2.1: Conventional Object Model<br />
00 11<br />
00 11<br />
objMethod<br />
parAttr<br />
Object Parent<br />
000 111<br />
000 111<br />
000 111<br />
000 111 parAttr<br />
parMethod<br />
Figure 2.2: Composition Filters Object Model<br />
class-based language). All requests coming from the outside world are directly<br />
dispatched to the implementations in the Object itself, or one of its Parent<br />
objects. This is done transparantly, as is shown by using dotted arrows inside<br />
the Object. Also, all instance variables intrinsically are available to the outside<br />
world, although some languages de ne some restrictions on this. 1<br />
2.1.2 Composition Filters Object Model<br />
The Composition Filters Object Model is an extension of the Conventional<br />
Object Model. This Composition Filters Object Model adds semantics to the<br />
object model by placing lters on top of the object interface. These lters are<br />
capable of investigating all incoming <strong>and</strong> outgoing messages, as well as the<br />
object itself, <strong>and</strong> it is capable of modifying passing messages, or forward them<br />
to other objects. A picture of the Composition Filters Object Model is found<br />
in Figure 2.2.<br />
1. For example private, protected <strong>and</strong> public attributes <strong>and</strong> methods in C ++ (Ellis <strong>and</strong><br />
Stroustrup 1990)
2.2. Design Patterns 9<br />
This gure shows the same situation of Figure 2.1, but now <strong>with</strong> Composition<br />
Filters extensions. All incoming messages from the outside world pass<br />
the input lters of the Object. These lters send one type of message to the<br />
method present in the Object itself, while the other message types are delegated<br />
to the Parent object (which has its own lters of course). In contrast to<br />
the conventional situation, this Parent object is a real object, but its presence is<br />
hidden from the outside world. Also, the internal calls to the implementations<br />
is explicit.<br />
There are three fundamental di erences between the two models:<br />
1. In the Composition Filters Object Model the Parent object is a real<br />
rst-class object, while in the Conventional Object Model it is not;<br />
2. In the Composition Filters Object Model there is one entrypoint for all<br />
incoming messages, 2 while in the Conventional Object Model all methods<br />
have their own individual entry points|this means that no overall<br />
control is possible over incoming messages in the Conventional Object<br />
Model, because message entry is not explicitly modelled in this model.<br />
3. Distribution of the incoming messages over the present implementation(s)<br />
is done by the lters in the Composition Filters Object Model,<br />
while in the Conventional Object Model, this is de ned by the execution<br />
model of the language in question. 3<br />
2.2 Design Patterns<br />
A design pattern is an entity, which gives one or more context-dependent solutions<br />
for a particular problem, or an implementation structure for a particular<br />
design issue. Patterns were rst introduced by Alex<strong>and</strong>er (1977), who de ned<br />
patterns for the architectural world. The software community has borrowed this<br />
idea, <strong>and</strong> nowadays many patterns are de ned to capture software design.<br />
These software design patterns have proven to be an e ective medium<br />
for documentation <strong>and</strong> communication about domain knowledge (Gamma et al.<br />
1995, Buschmann, Meunier, Rohnert, Sommerlad <strong>and</strong> Stal 1996, Pree 1994).<br />
Their description is formalized by Gamma et al. (1995), <strong>and</strong> most design patterns<br />
de ned today are formatted conform their recipe.<br />
2. There is also one exit point for all outgoing messages. We do not depict this often explicitly<br />
in this thesis, but the reader must know that they exist.<br />
3. There are di erent implementations. In C ++ for example, there are things called virtual<br />
tables, which are in fact pointers to the actual function implementations for the \current"<br />
object. In Smalltalk the runtime engine searches for appropriate implementations in the class<br />
hierarchy.
10 Chapter 2. Background <strong>and</strong> related work<br />
2.3 Position of this work in the TRESE project<br />
Composition Filters Development<br />
By development of Composition Filters, we mean the development of the model<br />
<strong>and</strong> the de nition of di erent lter types. At the moment, the model is considered<br />
more or less complete, so there is not much work in this area now.<br />
Composition Filters Implementations<br />
Several implementations of Composition Filters are developed <strong>and</strong> others are<br />
under development. Implementations in C ++ (Gl<strong>and</strong>rup 1995) <strong>and</strong> Smalltalk<br />
(Mordhorst <strong>and</strong> van Dijk 1996) are ready. Another kind of implementation is<br />
the Message Manipulator de ned by Stuurman (1996), who de ned Composition<br />
Filters as rst-class objects in an object-oriented environment. An implementation<br />
in Java is being examined.<br />
Composition Filters Knowledge Distribution<br />
A lot of articles have been written which address several problems that Composition<br />
Filters can solve (Bergmans 1994, Aksit, Bosch, van der Sterren <strong>and</strong><br />
Bergmans 1994, Aksit, Wakita, Bosch, Bergmans <strong>and</strong> Yonezawa 1993, Aksit,<br />
Bergmans <strong>and</strong> Vural 1992, Aksit <strong>and</strong> Bergmans 1992, Aksit <strong>and</strong> Bosch 1994).<br />
With these articles, we try to make the outside world aware of potentional problems<br />
in daily object-oriented designs, <strong>and</strong> how one can avoid these problems.<br />
Besides the distribution of articles, also courses are lectured in objectoriented<br />
analysis <strong>and</strong> design. Further, there is an active participation in conferences<br />
<strong>and</strong> workshops which address object-orientation.<br />
Composition Filters Deployment<br />
There are several framework designs which use the Composition Filters Object<br />
Model. These include Algra (1994), Koehorst (1994), Tekinerdogan (1994) <strong>and</strong><br />
Vuijst (1994).<br />
Where does this thesis t in<br />
The work in this thesis is part of the Composition Filters Knowlegde Distribution.<br />
We think the bene ts of this work is twofold. First, we show how certain<br />
design issues can be addressed using Composition Filters. Second, by expressing<br />
our implementations as Design Patterns, we make our knowledge accessible to<br />
the world.
Chapter 3<br />
Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
In our daily lives we often have to deal <strong>with</strong> relatively complex materials. It is<br />
common practice then to look at the problem from di erent points of view. We<br />
will focus on a certain aspect of the problem, <strong>and</strong> forget the rest for a moment.<br />
With this simple trick we are able to underst<strong>and</strong> things that are so complex,<br />
that we could never have understood them otherwise.<br />
In this chapter, we will elaborate on the domain of views. This is how we call<br />
\the trick" when applied to software engineering. We will see how software<br />
models can be made better <strong>and</strong> easier to underst<strong>and</strong> by making views explicit<br />
in the software model.<br />
The goal of this chapter is twofold. First, we will introduce the modelling<br />
issue <strong>Multiple</strong> <strong>Views</strong> in Section 3.1. Second, we show how the concept can be<br />
modelled in C ++. In Section 3.2, we give an example implementation where<br />
the change scenario is implemented in C ++. Conclusions are summarised in<br />
Section 3.3.<br />
3.1 Modelling <strong>Multiple</strong> <strong>Views</strong><br />
In Section 3.1.1, we will show what views are, <strong>and</strong> try to give the reader enough<br />
basics to belief that views can be bene cial for h<strong>and</strong>ling complex software engineering<br />
problems. It should also give enough introduction of views to underst<strong>and</strong><br />
the rest of this chapter.<br />
In Section 3.1.2, we introduce a conceptual model of views. We will use<br />
this model as our reference throughout this chapter. It shows the di erent parts<br />
of the view model, <strong>and</strong> which changes we expect in implementations that are<br />
based on this model.<br />
These changes are detailed out in Section 3.1.3, in which we de ne a<br />
scenario where the di erent model changes are described in detail.<br />
11
12 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
3.1.1 What is a View?<br />
People often look at things around them from di erent viewpoints. This means<br />
that the same things get several di erent interpretations |even from the same<br />
person| dependent on how we look at them. We can see this often in crime<br />
scenes, where many di erent statements come from even so many witnesses.<br />
This is what we call a passive view, because the object is interpreted in several<br />
di erent ways, something this object cannot control.<br />
Also, people react di erently to the signals they receive from their environment.<br />
Some signals are always ignored, some are always accepted, <strong>and</strong> some<br />
are accepted only under certain conditions. Sometimes we even can react differently<br />
on the same signals in di erent situations. For example, when a total<br />
stranger asks your friend, say Joe,tomake him some co ee, this will probably<br />
have no e ect. It depends on the mood of Joe when some acquaintance asks the<br />
same question. When you ask it, Joe always will make your co ee (unless you<br />
just had an enormous ght of course). He will also always make co ee for his<br />
girlfriend, but he knows she does not want her co ee as strong as you want it.<br />
We will call this kind of views active, because Joe can decide for himself how<br />
he will react on the question of making co ee.<br />
These situations are very normal in our daily lives. When we model software<br />
implementations however, we tend to forget this quickly, <strong>and</strong> make all behaviour<br />
of the software components general. This does not mean that views don't exist<br />
in software models, we just don't model them explicitly.<br />
Communication happens always between two or more parties. There will<br />
always be at least one sender <strong>and</strong> one receiver of a communication message.<br />
We cannot model the passive view (i.e. the interpretation of the data that<br />
is returned from the receiver to the sender) of this communication. We can<br />
however model the active view that the receiver provides to the sender.<br />
In normal life, an active view is often dependent of the context of the communication<br />
message | think of Joe who does respond to you or an acquaintance,<br />
while ignoring a total stranger.<br />
We also want this in software models. We want to de ne communication<br />
channels explicitly. Di erent channels require di erent |or at least partly<br />
di erent| interfaces. When we model each communication channel on its own,<br />
an object appears to have an interface that in fact consists of several subinterfaces,<br />
each supporting a di erent communication channel.<br />
This division of the interface of an object is depicted in Figure 3.1. We<br />
call these sub-interfaces views. Our goal is to make views explicit in our implementations.<br />
This helps us underst<strong>and</strong>ing the communication channels that<br />
exist between di erent objects, <strong>and</strong> the respective responsibilities of the communication<br />
participants. Further, <strong>with</strong> explicit views we are able to test these<br />
views <strong>and</strong> therefore construct more robust applications, where misuse errors are
3.1. Modelling <strong>Multiple</strong> <strong>Views</strong> 13<br />
Channel 1<br />
Object Interface<br />
Chan 1 interf. Common interf. Chan 2 interf.<br />
Channel 2<br />
Figure 3.1: <strong>Multiple</strong> <strong>Views</strong> in an object-oriented environment
14 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
State<br />
spaces<br />
Relation<br />
S(t)<br />
S(o)<br />
S(c)<br />
Object<br />
functionalities<br />
Real-World<br />
<strong>Views</strong><br />
less likely to occur.<br />
Transformation functions<br />
T(v(2))<br />
T(v(1))<br />
T(M)<br />
T(v(3))<br />
T(R)<br />
M(o)<br />
Conceptual<br />
<strong>Views</strong><br />
v(1)<br />
v(2)<br />
Methods<br />
v(3)<br />
V(o)<br />
<strong>Views</strong><br />
Mapping functions<br />
Figure 3.2: Conceptual Model of <strong>Multiple</strong> <strong>Views</strong><br />
3.1.2 Conceptual View Model<br />
To be able to make a good implementation of views in an object-oriented system,<br />
we must rst supply the conceptual model of views. This model captures the<br />
di erent aspects of views, <strong>and</strong> gives us a reference model from which we will<br />
explore the whole domain.<br />
In Figure 3.1 we can see that views are de ned at the interface of an<br />
object. If we do not de ne views, they will be present, but we cannot \see" them<br />
in that case. All we have is an object <strong>with</strong> its state space (see below). The model<br />
is depicted in Figure 3.2. It shows the real world, where views are a natural part<br />
of the system. <strong>Views</strong> are present implicitly, but they are nowhere referenced<br />
explicitly. We can make views explicit by making the appropriate abstractions<br />
of the state space. We call these abstractions transformation functions.<br />
Model Components<br />
In the real world, there are three di erent elements <strong>with</strong> respect to views.<br />
1. State spaces;<br />
2. Object functionalities;<br />
3. Some interconnection between these two.<br />
These elements are discussed in detail below. In Figure 3.2, we also see three<br />
di erent kinds of transformation functions:<br />
1. The transformation from object functionalities to methods;<br />
2. The transformation from state spaces to views;<br />
3. The mapping between views <strong>and</strong> methods.
3.1. Modelling <strong>Multiple</strong> <strong>Views</strong> 15<br />
These transformation functions re ect the realisation of speci cations into models.<br />
Conventionally, only the transformation T M is realised. We de ne views<br />
explicitly by realising the other transformations as well.<br />
Methods The methods implement the application semantics, i.e. the functionalities<br />
that the class provides. The set of methods that an object supports, is<br />
denoted as<br />
M o = Object Methods (3.1)<br />
The transformation function T M provides a method for each functionality. This<br />
transformation is rather trivial <strong>and</strong> common practice to developers, <strong>and</strong> it is<br />
not further discussed here.<br />
<strong>Views</strong> The views de ne the abstractions of the State Space we are interested<br />
in. Therefore we make the following de nitions.<br />
The Object StateSpace represents the total state space of the object that<br />
receives the message. This state space is multi-dimensional, <strong>and</strong> can be seen as<br />
all possible combinations of values of all internal variables.<br />
S o = Object StateSpace (3.2)<br />
The Context StateSpace represents the total multi-dimensional state<br />
space of the context of a message. This context consists of all possible information<br />
about the message, such as the sender of the message, the selector of<br />
the message (the method that is called), the parameters of the message <strong>and</strong> the<br />
target or server (the object that the message is sent to).<br />
S c = Context StateSpace (3.3)<br />
The Total StateSpace S t represents the cartesian product of S o <strong>and</strong> S c,<br />
<strong>and</strong> thus represents the total state space of a message. The actual state of a<br />
message when it is sent is denoted as s m.<br />
S t = S o S c (3.4)<br />
s m 2 S t (3.5)<br />
A view is the abstraction from a certain situation in the real world, so from<br />
all possible states s m 2 S t there are a couple of them that are part of this<br />
abstraction:<br />
v S t (3.6)<br />
Each view v needs its own transformation function T v, because each view can<br />
cover another aspect of the state space S t. Some examples of view aspects are<br />
sender information <strong>and</strong> message history information.
16 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
Methods<br />
<strong>Views</strong><br />
Figure 3.3: Many-to-many relationship between methods M o <strong>and</strong> views V o<br />
The set of views V o now can be de ned as follows. First, we de ne the<br />
powerset P(S t) of the state space, which represents the set of all possible combinations<br />
of states from the state space S t. The set of views V o of an object<br />
then is a subset of this powerset.<br />
V o P(S t) (3.7)<br />
A view v 2P(S t) (see Equation 3.6 <strong>and</strong> Equation 3.7), so a view is in<br />
e ect when the actual state of the message s m 2 v (See Equation 3.5).<br />
Method-View Coupling The coupling between the methods M o <strong>and</strong> the views<br />
V o is done by de ning a mapping between V o <strong>and</strong> M o. This mapping is many-tomany,<br />
as is shown in Figure 3.3. This mapping occurs in the following possible<br />
cardinalities:<br />
V 7! M + (surjection) (3.8)<br />
V + 7! M (injection) (3.9)<br />
The possibilities V 7! M <strong>and</strong> V + 7! M + are both constructed from the two<br />
mentioned here.<br />
Implementation Requirements<br />
When the concepts of the previous section are implemented, wewant to preserve<br />
the exibility that the object-oriented paradigm has given us. As we have seen<br />
in Equation 3.6, a view is a set of states. When we de ne more views on an<br />
object, we also want to be able to manipulate these views using normal set<br />
operators (see Figure 3.4).<br />
Also, we want to be able to manipulate the transformation functions by<br />
de ning extensions to existing models (i.e. through subclassing) <strong>with</strong>out any<br />
unnecessary rede nitions. We want to be able to make changes, following the<br />
scenario discussed in Section 3.1.3. The changes that we want tocover are:
3.1. Modelling <strong>Multiple</strong> <strong>Views</strong> 17<br />
View<br />
Subview 1 Subview 2<br />
(a) View Partitioning<br />
View 1 View 2<br />
Combined View<br />
(b) View Composition<br />
Figure 3.4: Set Operations on <strong>Views</strong><br />
Add views;<br />
Partition views;<br />
Extend views;<br />
Add behaviour;<br />
Extend behaviour;<br />
Combine views.<br />
Note that removal of behaviour <strong>and</strong> views is not listed here. This operation<br />
also is not supported by the inheritance mechanism provided by object-oriented<br />
languages.<br />
3.1.3 Scenario of Changes<br />
In this section we describe a scenario, which covers the possible changes that<br />
can be made to an object model that incorporates views. In Section 3.1.2, we<br />
have described a model for views in an object-oriented environment. When we<br />
implement this model, we have to transform the elements of the view model<br />
to the object model that is used for the implementation. This transformation<br />
is not trivial, as we will see in the next section, <strong>and</strong> depends heavily on the<br />
implementation language.<br />
The scenario starts <strong>with</strong> an object model, where views are not present<br />
yet. The interface is assumed public, so all methods are visible to all potential<br />
clients. We will start from that point, <strong>and</strong> rst add view semantics to the model.<br />
Then we follow a scenario of changes to this model. This scenario will show how<br />
easy (or hard) it is to adjust an object model <strong>with</strong> views.<br />
Add <strong>Views</strong><br />
In order to be able to de ne views on the interface of a class, we have to identify<br />
a mapping between the view model <strong>and</strong> the object model. The view model has<br />
three types of transformations (see Figure 3.2). The transformation of views<br />
needs special attention, because we have to be able to cover all possible forms<br />
of transformations, like sender <strong>and</strong> history information.
18 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
In the example that we will discuss in Section 3.2, we need the following<br />
categories of transformations (these are all view transformations):<br />
Access Control We need to provide some means of access control to the methods<br />
we have de ned. We want to restrict the interface of a class to one<br />
or more other classes in such a way, that only classes that are granted<br />
access can use the object, <strong>and</strong> others can not.<br />
Context Information We need a way of determining context information<br />
about a message. For example, if we want to prevent access from some<br />
class to one or more methods, we need to know what object sent the<br />
message.<br />
Meta Information We need to determine the type of an object at runtime. In<br />
other words, we need some meta information about objects <strong>and</strong> classes.<br />
History Information Sometimes we want to de ne views that are not based<br />
on the actual situation, but on the things that have happened in the<br />
past. In this situation we need to be able to deduce history information<br />
about messages from the objects.<br />
View Partitioning<br />
Sometimes we want to partition a view into two or more views. This is the<br />
consequence of re ning some part(s) of the speci cation. Suppose we have a<br />
view v 2 V o, i.e. the original view that we want to re ne. We de ne the partition<br />
v = 1 [ 2;:::<br />
Note that i 2P(S t), because V o 2P(S t), where P(S t) is the powerset of S t.So<br />
we can conclude that the partitions i are ordinary views on the object! They<br />
only have an extra property, which is that they together form the original view,<br />
thus i 2P(V o).<br />
Partitioning a view into several sub-views, in a way invalidates the original<br />
view. Thus, all references made to this view also must be removed.<br />
View Extension<br />
Extending a view means enlarging the set of possible values under which the<br />
view is active. The requirements only involve changing the view v 2 V o, <strong>and</strong><br />
thus the set V o. The identi er of this view remains the same, in contrast <strong>with</strong><br />
Section 3.2.3, where we will see a change of the view set V o, the identi ers<br />
inclusive. The encapsulation property of the implementation ensures us that in<br />
this case only the implementation of this view needs to be rewritten.<br />
Add Behaviour<br />
When we add behaviour to an object, we need to extend the method set M o<br />
of the object (see Equation 3.1). Also, the new behaviour probably falls under<br />
one or more views that are de ned on the object, so the set of mappings also<br />
needs to be extended.
3.1. Modelling <strong>Multiple</strong> <strong>Views</strong> 19<br />
Behaviour Extension<br />
Behaviour extension can have the following interpretations.<br />
Application Behaviour Extension This form of behaviour extension is the normal<br />
one, for which the inheritance mechanism of object-oriented languages is<br />
used. The original behaviour is \overwritten" <strong>with</strong> another one, so that all objects<br />
of the new (sub)class have the adapted behaviour. Note that this form of<br />
behaviour extension is static, i.e. it yields for all objects of this class.<br />
In terms of the view model discussed in Section 3.1.2, the extension of<br />
application semantics maps to the extension of the object functionalities, <strong>and</strong><br />
the addition of a mapping from this functionality to an object method m 2 M o.<br />
Meta Behaviour Extension Meta behaviour extension is totally di erent, because<br />
it does not really adapt the normal behaviour of the objects. It interprets<br />
the in- <strong>and</strong> outgoing messages of objects, <strong>and</strong> according to this information the<br />
behaviour of the object can be changed. So, object behaviour can (but does not<br />
have to) change because of meta behaviour extension, but when it does, it will<br />
be indirectly. Also this form of extension is static.<br />
Meta behaviour extension does not alter the method set M o. It does alter<br />
the view set, where a view is added or extended, that uses not only object state<br />
space information from S o, but also context state space information from S c,<br />
where information about the message is used to check for the validity of the<br />
view.<br />
Dynamic Behaviour Extension Dynamic behaviour extension can be application<br />
as well as meta behaviour extension. The extra property here is dynamicity.<br />
Not all objects of the new class have to get the new behaviour. It is also possible<br />
that not all invocations to the same object result in the same behaviour. This<br />
dynamicity isanimportant property that must be used in an implementation<br />
where close resemblance of the real world is necessary.<br />
We can see this as follows in the model of Section 3.1.2. In Figure 3.2,<br />
we see a mapping between object functionalities <strong>and</strong> object methods. Normally,<br />
this mapping results in one method per functionality (ignoring the fact that this<br />
method will almost always be divided in several smaller methods). It is possible<br />
however, that two di erent implementations exist for one object functionality.<br />
Depending on some view speci cations, one or the other implementation for the<br />
message will be activated.<br />
Think for example of an object class Collection, where the implementation<br />
of the sort message is dependent of the size of the collection (i.e. the<br />
actual number of elements). The behaviour of the sort message then is dynamic.<br />
The needed implementation can be chosen at runtime, depending on some state<br />
information. When we de ne the needed states in views, we choose <strong>and</strong> activate<br />
the best implementation depending on the current object state. So in our exam-
20 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
ple, the sort functionality has two implementations: quickSort <strong>and</strong> bubbleSort.<br />
The views for these methods are smallCollection <strong>and</strong> largeCollection. When we<br />
map, for the message sort, the view smallCollection to the method bubbleSort<br />
<strong>and</strong> the view largeCollection to the method quickSort, we have implemented a<br />
system where the object itself chooses the best implementation for a speci c<br />
behaviour at runtime, depending on some view speci cation.<br />
View Composition<br />
<strong>Views</strong> can be partitioned, as is discussed in Section 3.1.3, but they also can be<br />
composed. This means that two or more di erent views together de ne another<br />
view which is used to express some situation. With this mechanism it is possible<br />
to build a hierarchy of views, so that mappings to methods can be performed<br />
at an arbitrary granularity.<br />
Further, when two object classes are combined through inheritance, their<br />
state spaces also will be combined. It is very likely that methods of the rst<br />
object have to be restricted by views of the second object, so that additional<br />
mappings between methods <strong>and</strong> views have to be de ned. This mapping however<br />
crosses class boundaries, which is not a trivial thing to do.<br />
3.2 C++ Implementation<br />
Now wehave a clear overview of what views are, <strong>and</strong> what changes we want to<br />
be able to perform on a view implementation. We de ne an example on which<br />
we can test these changes. In the previous section, we listed the changes that<br />
we want to perform. We map these changes directly to our example. We start<br />
<strong>with</strong> a fresh example <strong>with</strong>out any views, <strong>and</strong> then, in six di erent stages, we<br />
extend our speci cation following the steps of Section 3.1.3. In Figure 3.5, we<br />
see the Mail class, <strong>and</strong> all subsequent subclasses that implement the steps of<br />
the scenario. Note that the scenario must be read from top to bottom.<br />
As the legend says, the white coloured classes are classes <strong>with</strong> application<br />
semantics. They are present because they have direct meaning for the<br />
program. The light-grey coloured classes also implement application semantics,<br />
but this is <strong>with</strong> a lot of overhead. This means that the implementation is heavy<br />
relative to its functionality. The dark-grey coloured classes are pure overhead.<br />
The . . . User classes mostly only implement a test function. The Object class<br />
implements runtime type information. This is necessary for the meta information<br />
we use in our implementation, <strong>and</strong> also for declaring \typeless" function<br />
arguments. 1 We can see that the Object class is pure overhead, <strong>and</strong> it also<br />
requires us to de ne overhead code in all subclasses of it, in order to let the<br />
Object functions return correct values. Finally, the MVMailH<strong>and</strong>ler class<br />
1. C ++ is strictly typed, which means that a function <strong>with</strong> an argument oftype Object can<br />
only be passed arguments of type Object, or a subtype of this type.
3.2. C ++ Implementation 21<br />
Object<br />
SecureDocument<br />
Legend<br />
User<br />
MVUser<br />
VPUser<br />
GroupUser<br />
PGPUser<br />
Warning2User<br />
ProtectedUser<br />
Normal class<br />
Normal class (<strong>with</strong> overhead)<br />
Overhead class<br />
Mail<br />
UserSystemViewMail<br />
OriginatorReceiverViewMail<br />
GroupMail<br />
SecureMail<br />
Warning2Mail<br />
ProtectedMail<br />
Figure 3.5: <strong>Multiple</strong> <strong>Views</strong> Scenario<br />
MailH<strong>and</strong>ler<br />
MVMailH<strong>and</strong>ler<br />
Add <strong>Views</strong><br />
Partition <strong>Views</strong><br />
Extend <strong>Views</strong><br />
Extend Behaviour (dynamic)<br />
Extend Behaviour (static meta)<br />
Compose <strong>Views</strong><br />
Scenario direction
22 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
is only present because introducing views means adapting the class interface of<br />
UserSystemViewMail.<br />
Now we will describe the running example. It covers the implementation<br />
of a Mail System. This system is capable of sending <strong>and</strong> receiving mail messages<br />
from <strong>and</strong> to users via a so-called mail h<strong>and</strong>ler. The idea is that a user creates a<br />
mail message, <strong>and</strong> sends it to the mail h<strong>and</strong>ler. This mail h<strong>and</strong>ler then routes<br />
the mail message <strong>and</strong> delivers it to the recipient. For clarity, we provide a list<br />
of terminology here.<br />
MailMessage The mail message that is to be sent from one user to another.<br />
MailOriginator The user that sends a MailMessage.<br />
MailReceiver The user that receives a MailMessage.<br />
User A user of the mail system, i.e. a MailOriginator or a MailReceiver.<br />
MailH<strong>and</strong>ler The system that receives a MailMessage from a User (the Mail-<br />
Originator) <strong>and</strong> routes it to the appropriate User (the MailReceiver).<br />
3.2.1 Simple Mail System<br />
In this section we show the implementation of the Simple Mail System. It only<br />
implements the normal expected semantics <strong>with</strong>out views. It provides a real<br />
executable mail system.<br />
To implement this system, we introduce the following classes:<br />
MailH<strong>and</strong>ler This class implements the central post o ce that routes Mail-<br />
Messages from <strong>and</strong> to Users.<br />
User This class implements the person objects that send <strong>and</strong> receive MailMessages<br />
from <strong>and</strong> to each other (the MailOriginator <strong>and</strong> the MailReceiver<br />
objects).<br />
Mail This class implements the MailMessage itself. The <strong>Multiple</strong> <strong>Views</strong> that<br />
this chapter is about will be de ned on this class, so this is the only<br />
real important class of the example. The other two classes are present to<br />
support the example.<br />
Note that we only elaborate on the MailMessage de nition, because the User<br />
<strong>and</strong> the MailH<strong>and</strong>ler classes only are present to support the example. The<br />
class Mail has the following interface speci cation:<br />
setMailOriginator This method is used to set the originator of the MailMessage.<br />
getMailOriginator This method is used to inspect who sent the MailMessage.<br />
setMailReceiver This method is used to indicate to whom the MailMessage is<br />
to be sent.<br />
getMailReceiver This method is used to inspect the receiver of the MailMessage.<br />
setMailContents This method is for setting the contents of the MailMessage.<br />
getMailContents This method is used to inspect the contents of the MailMessage.<br />
send This method is used to send the MailMessage to the indicated MailReceiver.
3.2. C ++ Implementation 23<br />
MailOriginator MailMessage MailH<strong>and</strong>ler MailReceiver<br />
setMailOriginator<br />
setMailReceiver<br />
setMailContents<br />
send<br />
send<br />
getMailReceiver<br />
getMailContents<br />
approve<br />
setRoute<br />
setDelivered<br />
getMailOriginator<br />
getMailContents<br />
receive<br />
Figure 3.6: Object Interaction Diagram for the Mail System<br />
reply This method is used to send a reply to the MailOriginator.<br />
approve This method is used to tell the MailMessage that it is approved for<br />
delivery by the MailH<strong>and</strong>ler.<br />
isApproved This method is used to inspect if the MailMessage is approved for<br />
delivery.<br />
setDelivered This method is used to set the indication that the MailMessage is<br />
delivered to the MailReceiver.<br />
isDelivered This method is used to inspect if the MailMessage is delivered to<br />
the MailReceiver.<br />
setRoute This method is used to set the routing information of the MailMessage.<br />
getRoute This method is used to inspect the routing information of the Mail-<br />
Message.<br />
In Figure 3.6, the expected runtime behaviour of the system is displayed. Certain<br />
details are omitted here for simplicity. The order of the messages setMailOriginator,<br />
setMailReceiver <strong>and</strong> setMailContents from the MailOriginator to the<br />
MailMessage is irrelevant. Further, the MailOriginator will be inspecting the<br />
instance variables of the MailMessage via the get. . . methods.<br />
The implementation of this system is rather straightforward. The C ++<br />
implementation is listed in Appendix A.1.<br />
An interesting detail in Figure 3.6 is the call of getMailContents by the Mail-<br />
H<strong>and</strong>ler. This is unauthorised use of the method (we do not want the postman<br />
to read our love letters), <strong>and</strong> we want to prevent this in the next version of our
24 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
Mail System.<br />
setMailOriginator<br />
getMailOriginator<br />
setMailContents<br />
getMailContents<br />
setMailReceiver<br />
getMailReceiver<br />
send<br />
reply<br />
approve<br />
isApproved<br />
setDelivered<br />
isDelivered<br />
setRoute<br />
getRoute<br />
p<br />
p p<br />
p<br />
p<br />
p<br />
p p<br />
p<br />
p<br />
p<br />
p p<br />
p<br />
p p<br />
p<br />
p p<br />
UserView SystemView<br />
Table 3.1: Access rules for the Mail System<br />
3.2.2 Add <strong>Views</strong>: UserSystemView Mail System<br />
In the Simple Mail System we saw the implementation of a straightforward<br />
mailing system. It was capable of sending MailMessages from one User (the<br />
MailOriginator) to another (the MailReceiver) through the MailH<strong>and</strong>ler. Now<br />
we are going to extend this system <strong>with</strong> views.<br />
Motivation<br />
We want to divide the interface of Mail into di erent views, that clearly separate<br />
the di erent functionalities that the interface provides.<br />
We saw in Figure 3.6 that the MailH<strong>and</strong>ler was peeking into the Mail-<br />
Message. With the application of views, wewant to prevent such misuse in the<br />
future.<br />
The interface of Mail is rather \big" already. When the number of<br />
methods grows even larger, it is not clear anymore which methods serve what<br />
purpose. Being able to see the sub-interfaces of a relatively large class interface<br />
makes this interface much more readable.<br />
Semantic Structure<br />
As can be seen in Figure 3.6, there are two di erentinterfaces in the class Mail.<br />
These are the UserView <strong>and</strong> the SystemView. Some methods only apply for<br />
Users, <strong>and</strong> some other methods only apply for the MailH<strong>and</strong>ler of the system.<br />
There are also methods that have no restrictions. Wewant to divide the interface<br />
of class Mail as follows.<br />
To be able to implement this, we augment the de nition of class Mail.<br />
These changes have the following bases (See also Section 3.1.3).
3.2. C ++ Implementation 25<br />
Access Control We need to provide some means of access control to the methods<br />
we have de ned. We want to restrict the interface of class Mail to<br />
the class User in such away, that User objects have noway in calling<br />
the SystemView methods approve, setDelivered <strong>and</strong> setRoute in Table 3.1.<br />
Context Information We need a way of determining context information<br />
about a message. For example, if we want to prevent access from a User<br />
to the method setRoute, we need to know which object sent the message.<br />
Meta Information We need to determine the type of an object at runtime<br />
(such asaUser). In other words, we need some meta information about<br />
objects <strong>and</strong> classes.<br />
Implementation Consequences<br />
In C ++, we do not have the Context state space S c (Equation 3.3), so we cannot<br />
support views that depend on this information <strong>with</strong>out providing it by h<strong>and</strong>.<br />
We need this information, because we want to restrict access dependent onthe<br />
type of the sender, <strong>and</strong> the sender is part of S c.<br />
We can only provide context state space information by explicitly passing<br />
the sender of the messages to the receiving object. This is of course not<br />
fool-proof, <strong>and</strong> error-prone. Furthermore, it needs modi cation of the class interfaces,<br />
which breaks reusability of classes <strong>with</strong>out view implementations in<br />
classes <strong>with</strong> a view implementation. This means a lot of (unnecessary) recoding<br />
of methods when views are added to a class dictionary. This is seen in the example<br />
in Appendix A.2, where the User <strong>and</strong> the MailH<strong>and</strong>ler classes have<br />
to be rede ned only because the interface of Mail has changed.<br />
We also have a problem <strong>with</strong> the mapping between the methods M o <strong>and</strong> the<br />
views V o. There is no way ofintercepting an incoming message in a central place<br />
in an object, in order to test for the mapping relation. The only way of testing<br />
the mapping relation is in the method de nition itself. But in doing so, we are<br />
integrating the methods M o <strong>with</strong> the mappings, which is not what we want. To<br />
avoid this, we de ne the methods M o in a private section of the object, so the<br />
outside world cannot use it. These private methods implement the application<br />
semantics, while the public methods implement the method-view mappings.<br />
This approach has one drawback. The overview of the class interface is<br />
lost again (we wanted to approve this <strong>with</strong> views) because of the enormous<br />
amount of methods that appear. The UserSystemViewMail class from Appendix<br />
A.2 has a lot of methods (33!), while we wanted only the 15 of the<br />
non-view implementation from the Mail class from Appendix A.1.<br />
The origin of this problem lies in the N : M relation between methods<br />
M o <strong>and</strong> views V o. We can only intercept at the method entrance point. When<br />
we have one method that couples to more than one view, this is no problem.<br />
With views however, we often have a view, which is coupled to a number of<br />
methods. We can only implement this by repeating coupling information for
26 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
each method.<br />
The views V o are implemented using Boolean functions. This provides a central<br />
de nition of the views, so they can be reused in the rest of the class speci cation,<br />
<strong>and</strong> they can also be rede ned easily <strong>with</strong>out recoding other parts of the class<br />
speci cation.<br />
However, we need information we do not have. We need to deduce the<br />
type (class) of the sender object, in order to decide if access is allowed. This type<br />
of meta-information is not present inC ++, <strong>and</strong> must explicitly be implemented.<br />
The scheme that is used in many commercial class libraries does the job pretty<br />
well.<br />
The implementation in Appendix A.2 uses an internal Mail object in User-<br />
SystemViewMail. One could have expected an inheritance relation here. We<br />
have not done this, because the interface had to be rewritten completely, <strong>and</strong> it<br />
is impossible to completely hide the interface of the parent class <strong>with</strong>out losing<br />
the inheritance bene ts.<br />
The interface of Mail must be made invisible. If we don't do this, the<br />
application still can call the old versions of the methods (by omitting the sender<br />
parameter). So the Mail class must be made protected or private. But then<br />
we cannot pass the UserSystemViewMail objects to functions that expect<br />
Mail objects as a parameter. We can trick this by explicitly casting the parameter<br />
to be of class Mail, but then the called function can freely access the<br />
old de nitions of the functions. This will not bring us any further, so to avoid<br />
complications, we de ned the Mail object as an internal variable of User-<br />
SystemViewMail.<br />
In Figure 3.7, we see a piece of code de ning views in a C ++ class. This example<br />
is an extract of Appendix A.2, <strong>and</strong> has all the elements in it that we discussed in<br />
this section. All interface methods have the context parameter sender de ned.<br />
Also, the interfaces are separated from the implementation, which separates<br />
application semantics from method-view mappings. The views are de ned as<br />
Boolean functions, <strong>and</strong> the class must inherit from some generic class Object<br />
which provides runtime type information.<br />
3.2.3 View Partitioning: OriginatorReceiverView Mail System<br />
In the UserSystemView Mail System we saw a Mail System that separated the<br />
Mail interface in a part for the Users, <strong>and</strong> a part for the MailH<strong>and</strong>ler. In this<br />
section we re ne the UserView.<br />
Motivation<br />
In this section we are going to divide a view into several sub-views. With this, we<br />
show the (non-) exibility <strong>and</strong> composability of the implementations of views.
3.2. C ++ Implementation 27<br />
class UserSystemViewMail : public Object<br />
f<br />
public:<br />
virtual classTypes myClass(void)<br />
f return UserSystemViewMailClass; g<br />
virtual void setMailOriginator(Object ,MVUser );<br />
:::;<br />
protected:<br />
virtual int isUserView(Object );<br />
virtual int isSystemView(Object );<br />
private:<br />
virtual void pureSetMailOriginator(MVUser );<br />
:::;<br />
g;<br />
void<br />
UserSystemViewMail::setMailOriginator(Object sender,MVUser u)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender), this!pureSetMailOriginator(u));<br />
g<br />
int<br />
UserSystemViewMail::isUserView(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return sender!isKindOf(MVUserClass);<br />
g<br />
void<br />
UserSystemViewMail::pureSetMailOriginator(MVUser u)<br />
f<br />
mail!setMailOriginator(u);<br />
g<br />
Figure 3.7: Adding <strong>Views</strong> in C ++
28 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
Semantic Structure<br />
setMailOriginator<br />
setMailContents<br />
getMailContents<br />
setMailReceiver<br />
send<br />
reply<br />
OriginatorView ReceiverView<br />
p<br />
p<br />
p p<br />
p<br />
p<br />
p<br />
Table 3.2: Separation of UserView methods<br />
In the UserSystemView Mail System, we saw the implementation of a mailing<br />
system which had two views. These views separated the interface of Mail into<br />
a part that was accessible to the Users, <strong>and</strong> one part for the MailH<strong>and</strong>ler.<br />
The UserView is too broad however. This view allows all Users inthesystem<br />
to manipulate all MailMessages in the system. In the OriginatorReceiverView<br />
Mail System, we are going to restrict this.<br />
Table 3.2 shows the separation of methods from the UserView in the<br />
UserSystemView Mail System into the two views OriginatorView <strong>and</strong> Receiver-<br />
View. Note that this is not a total partitioning. From all Users in the system,<br />
only the MailOriginator <strong>and</strong> the MailReceiver will have some access to the<br />
MailMessage. All other Users will have no access at all. Also note that methods<br />
<strong>with</strong>out any access restrictions are not listed here.<br />
We have to de ne the new views, <strong>and</strong> wehave to attach the methods from<br />
Table 3.2 to the views. Note that we donot rede ne any application semantics<br />
(from the original Mail class).<br />
Implementation Consequences<br />
Implementing this view partitioning in C ++ has the following consequences. The<br />
view set V o has changed, so we need a couple of extra functions to implement<br />
these views. Further, all method-views couplings that refer to the UserView<br />
have to be rewritten. Now the shortcomings of the C ++ solution mentioned in<br />
Section 3.2.2 becomes clear. All methods that de ne a method-view coupling<br />
<strong>and</strong> refer to the view UserView have to be rewritten. In Figure 3.8 we can see<br />
this. When we had been able to use a central place for this coupling, we could<br />
have avoided this situation.<br />
3.2.4 View Extension: Group Mail System<br />
The OriginatorReceiverView Mail System provided a secure access to the Mail-<br />
Message for only those users that were in any way related to the MailMessage.<br />
In this section we are going to extend the view semantics.
3.2. C ++ Implementation 29<br />
class OriginatorReceiverViewMail : public UserSystemViewMail<br />
f<br />
public:<br />
virtual void setMailOriginator(Object ,MVUser );<br />
virtual void setMailReceiver(Object ,MVUser );<br />
:::;<br />
protected:<br />
virtual int isOriginatorView(Object );<br />
virtual int isReceiverView(Object );<br />
g;<br />
void<br />
OriginatorReceiverViewMail::setMailOriginator(Object<br />
sender,MVUser u)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isOriginatorView(sender),<br />
UserSystemViewMail::setMailOriginator(sender,u));<br />
g<br />
int<br />
OriginatorReceiverViewMail::isOriginatorView(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return (this!getMailOriginator(this) (MVUser )0)<br />
jj sender this!getMailOriginator(this);<br />
g<br />
Figure 3.8: Partitioning <strong>Views</strong> in C ++
30 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
Motivation<br />
This section will show the implications of extending the view semantics.<br />
Semantic Structure<br />
The semantics of the OriginatorView is too restrictive for our purpose. When a<br />
User has created a MailMessage, he or she is the only one that can manipulate<br />
the MailMessage until it is sent to the MailReceiver.Wewant to be able to allow<br />
all members of the same group of Users to manipulate MailMessages. In this<br />
way it is possible that a person of some group creates the MailMessage, another<br />
group member reviews it, <strong>and</strong> nally the secretary archives the MailMessage<br />
<strong>and</strong> sends it to the MailReceiver.<br />
Implementation Consequences<br />
Because we separated view de nitions from the rest of the class speci cation,<br />
we only have to de ne a new method for the OriginatorView. In Appendix A.4<br />
this is made clear. The only extras implemented besides the view are some test<br />
functions.<br />
3.2.5 Dynamic Behaviour Extension: Secure Mail System<br />
The GroupMail System extended the view semantics. Now we will add some<br />
extra behaviour to the Mail System.<br />
Motivation<br />
This section will show the consequences of extending the behaviour of the Mail<br />
System. We will implement dynamic behaviour here, showing that views are<br />
not only used for access control.<br />
Semantic Structure<br />
The Mail class implemented direct storage <strong>and</strong> retrieval of the MailContents<br />
until now. In this section we implement a new feature. The contents of the<br />
MailMessage will be encrypted using the PGP protocol automatically, when<br />
the participating Users support this protocol.<br />
This requirement introduces something special: We now have two different<br />
implementations for the same method(s). The setMailContents method<br />
must eventually encode the MailContents, <strong>and</strong> the getMailContents eventually<br />
must decode the MailContents to make it readable again.<br />
To implement this, we introduce a new view, PGPUserView, which is<br />
active when the User supports the PGP protocol. If this is true, the new encoding<br />
<strong>and</strong> decoding versions of setMailContents <strong>and</strong> getMailContents will be used.<br />
Otherwise the system will use the \normal" versions.<br />
This has the impact that only Users that support the protocol will be<br />
able to read messages that are encoded. This re ects the real world situation,
3.2. C ++ Implementation 31<br />
where a person cannot read PGP encoded messages when he does not support<br />
the protocol.<br />
Implementation Consequences<br />
For the implementation, we introduce the new view, PGPUserView, <strong>and</strong> couple<br />
this view to the methods getMailContents <strong>and</strong> setMailContents. Figure 3.9 shows<br />
that the new getMailContents now chooses implementation dependent on some<br />
view de nition. There are no further consequences besides those wehave already<br />
seen.<br />
3.2.6 Static Meta Behaviour Extension: Warning2 Mail System<br />
In this section we will extent the behaviour semantics in another way. We reify<br />
the messages <strong>and</strong> alter our behaviour depending on the obtained information.<br />
Motivation<br />
We want to show how meta information about messages can be used to reason<br />
about these messages.<br />
Semantic Structure<br />
In this section we extent the semantics of the Mail class in such away, that it<br />
may output a warning when one of the methods setMailOriginator, setMailReceiver,<br />
setMailContents or send is called, depending on some conditions.<br />
It adds something new to the system. We had methods M o, views V o<br />
<strong>and</strong> method-view mappings. Which one is changed when we want to add the<br />
desired behaviour?<br />
We said before in Equation 3.4 that context information about the messages<br />
(S c)was part of the total state space, from which views were abstracted.<br />
We have omitted a precise de nition about this state space. A part of this space<br />
consists of all information about the message that is sent, including the selector<br />
that indicates which method should be executed. Because message information<br />
is part of the state space S c, we can de ne a view that covers this part of the<br />
state space S t.<br />
The implementation of the view will be a problem however, because we<br />
access meta information about the message, something we did not do before.<br />
Implementation Consequences<br />
In C ++, we do not have information about a sent message. In Appendix A.2<br />
we already were confronted <strong>with</strong> this fact, because we needed the sender of the<br />
message. In this case we want other information about the message, namely<br />
the selector. This information is implicitly available, because we can see this<br />
in the method body itself. But because we have to count the number of times<br />
the message is sent, we need this information explicitly. This is not part of the<br />
language, so we need to implement this ourselves. Figure 3.10 shows us how it
32 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
class SecureMail : public GroupMail<br />
f<br />
public:<br />
virtual char getMailContents(Object );<br />
:::;<br />
private:<br />
virtual char purePGPGetMailContents(Object );<br />
g;<br />
char<br />
SecureMail::getMailContents(Object sender)<br />
f<br />
char s (char )0;<br />
if (this!isPGPUserView(sender)) f<br />
s this!purePGPGetMailContents(sender);<br />
g else f<br />
s GroupMail::getMailContents(sender);<br />
g<br />
return s;<br />
g<br />
char<br />
SecureMail::purePGPGetMailContents(Object sender)<br />
f<br />
char l, s strdup(GroupMail::getMailContents(sender));<br />
cout "PGP decoding...nn";<br />
for (l s; l;l++) ( l)--;<br />
return s;<br />
g<br />
Figure 3.9: Dynamic Behaviour Extension in C ++
3.2. C ++ Implementation 33<br />
typedef enum f<br />
W2MailSetMailOriginatorSelector,<br />
:::<br />
lastWarning2MailSelector<br />
g Warning2MailSelector;<br />
class Warning2Mail : public SecureMail<br />
f<br />
public:<br />
virtual void setMailOriginator(Object , MVUser );<br />
:::;<br />
private:<br />
int selectorCount[ lastWarning2MailSelector];<br />
g;<br />
void<br />
Warning2Mail::setMailOriginator(Object sender, MVUser u)<br />
f<br />
if (this!isWarning2View(W2MailSetMailOriginatorSelector)) f<br />
cout "Warning, setMailOriginator sent twicenn";<br />
g<br />
selectorCount[W2MailSetMailOriginatorSelector]++;<br />
SecureMail::setMailOriginator(sender,u);<br />
g<br />
Figure 3.10: Static Meta Behaviour Extension in C ++
34 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
can be done in C ++. Appendix A.6 shows the complete solution. The solution is<br />
rather ad-hoc however, <strong>and</strong> again repeats the method-view coupling more often<br />
than we want.<br />
An alternative implementation can explicitly build a meta object of the<br />
message, <strong>and</strong> pass it as a parameter to another method which does the counting<br />
<strong>and</strong> registration of incoming messages. At this point, this alternative would be<br />
too distracting for the example now.<br />
3.2.7 View Composition: Protected Mail System<br />
We have made several enhancements to the Mail System. We even added some<br />
level of security by applying the PGP protocol. But protection using security<br />
levels is still missing from the scene.<br />
Motivation<br />
We add the protection functionality, because we want to test how easily we can<br />
combine di erent views into one object. The existing views of Mail will be<br />
combined <strong>with</strong> the views of a new class SecureDocument, which acts as the<br />
security wall for the MailMessages.<br />
Semantic Structure<br />
The next version of the Mail System, the Protected Mail System, combines<br />
the existing views of the Warning2 Mail System <strong>with</strong> views that exist in the<br />
SecureDocument class.<br />
SecureDocument implements a securityClearance view <strong>with</strong> a security<br />
level attached to it. The view is active when the security level of the calling<br />
object is su cient <strong>with</strong> respect to the security level of the document.<br />
The implementation of this SecureDocument must conform to the<br />
<strong>Multiple</strong> <strong>Views</strong> semantics, because we are going to combine the views on SecureDocument<br />
<strong>with</strong> those on Warning2Mail.<br />
Because the user who wants to set or read the message contents has<br />
to have security clearance, we need to de ne a new user class that adds this<br />
functionality to Mail users. The class is called ProtectedUser, <strong>and</strong> has<br />
methods for setting <strong>and</strong> retrieving the security level of the user.<br />
The semantics of the getMailContents <strong>and</strong> the setMailContents will be<br />
enhanced, because the view securityClearance must be checked.<br />
Two di erent implementation alternatives are possible here. The SecureDocument<br />
only implements a view. This functionality can be included<br />
in the new ProtectedMail class directly, sothe implementation uses single<br />
inheritance. Another, more illustrative solution uses multiple inheritance, <strong>and</strong><br />
de nes SecureDocument as a separate class.<br />
The ProtectedMail class is the combination of the Warning2Mail <strong>and</strong> the<br />
SecureDocument classes. The view set thus is also the combination of the
3.3. Conclusions 35<br />
class SecureDocument:public Object f<br />
:::;<br />
protected:<br />
int isSecurityClearance(Object );<br />
:::;<br />
g;<br />
class ProtectedMail : public Warning2Mail, public SecureDocument<br />
f<br />
public:<br />
virtual void setMailContents(Object ,char );<br />
:::;<br />
g;<br />
void<br />
ProtectedMail::setMailContents(Object sender, char s)<br />
f<br />
CFilter(this!isSecurityClearance(sender),<br />
Warning2Mail::setMailContents(sender,s));<br />
g<br />
inherited views:<br />
Implementation Consequences<br />
Figure 3.11: View Composition in C ++<br />
[<br />
VprotectedMail = Vwarning2Mail VsecureDocument<br />
(3.10)<br />
In C ++ we use multiple inheritance to combine the classes Warning2Mail <strong>and</strong><br />
SecureDocument. In Figure 3.11 we can see that we only have to rewrite<br />
the method-view coupling of getMailContents <strong>and</strong> setMailContents, where we<br />
directly refer to view de nitions from parent classes (in this case SecureDocument).<br />
3.3 Conclusions<br />
In this chapter we have de ned a model for <strong>Multiple</strong> <strong>Views</strong>. Also, we listed the<br />
possible adaptations to the model, <strong>and</strong> de ned a running example that showed<br />
us how <strong>Multiple</strong> <strong>Views</strong> can be implemented in a \conventional" object-oriented<br />
language like C ++.<br />
We have seen that using such a language has several drawbacks when we<br />
want to implement a semantic-rich concept like <strong>Multiple</strong> <strong>Views</strong>. It turns out<br />
that C ++ lacks the following properties:
36 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong><br />
Static meta information, such as the class of an object, or the methods a<br />
certain class has. In short, we cannot ask some class or object questions<br />
about its de nition.<br />
Dynamic meta information, such as the sender <strong>and</strong> the parameters of a<br />
message, or information about when the message was sent. We have seen<br />
that all this information was to be given by the programmer, something<br />
we could not check <strong>and</strong> control.<br />
A central entrance point for all incoming <strong>and</strong> outgoing messages for an<br />
object, where we can guard <strong>and</strong> control what is going on in the objects.<br />
This has the consequence that we cannot neatly separate the methods<br />
from the views, <strong>with</strong>out making strict coding conventions, which of<br />
course are error-prone. Further, as we have seen already too often, that<br />
a lot of recoding was necessary, which was the consequence of a missing<br />
central entry point.<br />
In short we can say that implementing <strong>Multiple</strong> <strong>Views</strong> in a language like C ++<br />
is possible, but that it results in code that is not maintainable very well. One<br />
has to realise that a lot of recoding must be carried out when adaptations to<br />
the software models must be made. Moreover, one has to stick <strong>with</strong> coding<br />
conventions, because otherwise the scheme will simply not work. This is a very<br />
undesirable situation, because errors can easily occur, <strong>and</strong> are very di cult to<br />
detect.<br />
A lot of the exposed problems are there, because we wanted the views<br />
to be composable. Ifwe had implemented view semantics in the methods themselves,<br />
we could not have adapted views or method semantics independent from<br />
each other. This means that using views in the wrong way would have broken<br />
the reusability property of object oriented problems, therefore making the<br />
introduction of views in a software model not composable <strong>with</strong> other future<br />
adaptations of the system.<br />
Smalltalk implementation<br />
We did not give the example code in Smalltalk, but we will give some hints<br />
about it here.<br />
Access control We can not prevent objects from calling any method that is<br />
de ned at the interface of another object. This is a problem, because we separated<br />
the methods from the method-view mappings in our C ++ implementation,<br />
<strong>and</strong> made the original methods invisible for the outside world. We cannot do<br />
this in Smalltalk.<br />
Context information In Smalltalk, context information is not explicitly available.<br />
There is a possibility however to extract the sender of a message from the
3.3. Conclusions 37<br />
execution context of a message. This is not trivial however, <strong>and</strong> requires inside<br />
knowledge of the Smalltalk implementation that is used.<br />
Meta information In Smalltalk, every object in the system has a corresponding<br />
class associated <strong>with</strong> it, which we can access <strong>and</strong> inspect at runtime. So, meta<br />
information is fully available in Smalltalk.<br />
Central entry point for method execution We also have no special central entry<br />
point for methods in Smalltalk. Just like inC ++, wehave to separate methods<br />
from method-view mappings by renaming the original methods to something<br />
like pure.... We can prevent heavy rede nition of methods like inC ++ however<br />
by taking advantage of the doesNotUnderst<strong>and</strong> mechanism. If we do not de ne<br />
explicit normal methods, the Smalltalk runtime system cannot nd the method,<br />
<strong>and</strong> will raise an exception <strong>and</strong> call the doesNotUnderst<strong>and</strong> method. Here we<br />
could de ne global mappings for the entire object.
38 Chapter 3. Modelling Issue: <strong>Multiple</strong> <strong>Views</strong>
Chapter 4<br />
Modelling Issue: <strong>Layering</strong><br />
When we use something that does not completely satisfy our needs, we adapt<br />
it conform our wishes. The best way of doing this, is leaving the original thing<br />
intact, so others can use the original, <strong>and</strong> you have a clear overview of your<br />
changes.<br />
In this chapter we will cover the domain of layering. When adaptations to things<br />
(objects) are incremental, i.e. <strong>with</strong>out tampering <strong>with</strong> the original, we will call<br />
this incremental change a layer. When we want yet another change, we create<br />
another layer. In this way, several layers can be built upon one object, re ecting<br />
several successive adaptations.<br />
In Section 4.1 we discuss our layering model. Section 4.2 then covers the<br />
C ++ implementation of the de ned scenario <strong>with</strong> a running example. Conclusions<br />
are summarised in Section 4.3.<br />
4.1 Modelling Layers<br />
In Section 4.1.1 we introduce layering as a modelling mechanism. A more formal<br />
model will be presented in Section 4.1.2. Here we de ne the model itself, <strong>and</strong><br />
which changes we expect to occur in the model. Just as in the previous chapter,<br />
we then de ne a scenario which covers the di erent changes in the model in<br />
Section 4.1.3.<br />
4.1.1 What is <strong>Layering</strong>?<br />
People have the urge to arrange things. This is also the case <strong>with</strong> software<br />
components, <strong>and</strong> also <strong>with</strong>in software components. We already have seen that<br />
object interfaces can be divided into several sections, called views, to achieve<br />
complexity reduction. We call this vertical object division. In this chapter we<br />
will discuss horizontal object division, called layering. 1 <strong>Layering</strong> emerges from<br />
two activities:<br />
1. Compare Figures 3.1 <strong>and</strong> 4.4.<br />
39
40 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
Messages<br />
Object<br />
(a) Object <strong>with</strong>out layer<br />
Messages<br />
Object<br />
Layer<br />
(b) Object <strong>with</strong> layer<br />
Figure 4.1: Object Layers<br />
workHarder<br />
gotoSleep<br />
Person<br />
Employee<br />
Figure 4.2: Role playing modelled <strong>with</strong> a layer<br />
Messages<br />
Object+Layer<br />
(c) Layered Object seen<br />
from the outside world<br />
Extending happens when some object structure exists, <strong>and</strong> we need a (slightly<br />
modi ed) version of it. In that case, we take the existing structure as our<br />
starting point, <strong>and</strong> build our enhancements on top of it.<br />
Dividing happens when no object structure exists, <strong>and</strong> we are creating a new<br />
one. We want this new structure to be underst<strong>and</strong>able, maintainable <strong>and</strong><br />
reusable. Therefore we divide the structure into parts, <strong>and</strong> the individual<br />
objects into layers.<br />
In both ways, we go from the situation in Figure 4.1(a) where we just have an<br />
object, to the situation in Figure 4.1(b) where the object is wrapped in a layer.<br />
Note that the environment is not aware of the presence of the layer, it is<br />
as if one talks to one monolithic object (See Figure 4.1(c)).<br />
A lot of modelling issues can be represented by layers. Role playing for example<br />
can be extremely well modelled <strong>with</strong> a layered architecture. In Figure 4.2, we<br />
see a Person <strong>with</strong> a role Employee attached to it. When the role must be<br />
played (during working hours), the Employee layer will be activated. This can
4.1. Modelling Layers 41<br />
Hardware<br />
Drivers<br />
System functions<br />
Additional functions<br />
System utilities<br />
Figure 4.3: The Unix operating system divided into several layers<br />
be done using views.<br />
Layered architectures are found everywhere in software systems. The<br />
most well-known architecture is the OSI communication layered architecture<br />
described in Black (1991). This architecture divides the communication between<br />
software systems in seven di erent layers, each <strong>with</strong> its own tasks <strong>and</strong><br />
responsibilities. Each layer implements some communication protocol, using the<br />
underlying layer(s) as a communication medium.<br />
<strong>Layering</strong> in software systems is done for several reasons. One of the most important<br />
reasons for applying layering techniques is reduction of complexity. To<br />
achieve this, large software systems are divided into several layers, which can<br />
then be designed, built <strong>and</strong> maintained more or less independently of each other.<br />
Take for example the architecture of a traditional Unix system. In Figure 4.3<br />
we see that a clean division is made between the functionalities. This categorisation<br />
helps us to underst<strong>and</strong> the implementation of the system. Also in<br />
smaller-scale software systems, such as individual programs (or even program<br />
parts!), layering techniques can be used to reduce complexity.<br />
Another reason for using layering techniques, is separation of concerns.<br />
This separation also enables us to better underst<strong>and</strong> things. One often puts basic<br />
functionalities in the core, <strong>and</strong> then wraps around this core one or more layers<br />
<strong>with</strong> special functionalities. This improves the maintainability of the software<br />
system. In the next section we will introduce our model.
42 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
Layer 2<br />
Layer 1<br />
Layer 0<br />
Object<br />
(a) Outside world view<br />
4.1.2 Conceptual <strong>Layering</strong> Model<br />
Figure 4.4: Layered Object<br />
Layer 2<br />
Layer 1<br />
Layer 0<br />
(b) Detail view<br />
Object<br />
Until now, we have seen a layered object only from above, like in Figure 4.1(b).<br />
In Figure 4.4(a) we see another way of showing layers inside an object. This<br />
sideview shows a horizontal division of the object. Note that we donot see from<br />
the outside (from the interface) that the object is divided into several layers.<br />
Figure 4.4(b) shows us the internal structure of the object. It appears to consist<br />
of three individual objects that are related to each other. This relation will be<br />
discussed later in this chapter.<br />
We will describe the model of layering from three di erent viewpoints.<br />
Functionality. Functionalities from the requirement speci cation can be<br />
mapped to object implementations in di erent ways;<br />
Level. Layers can represent direct object functionalities, or functionalities<br />
that lay on a higher (meta) level;<br />
Structure. Layers can be attached to objects in a static (compile-time)<br />
or a dynamic (run-time) way.<br />
These are not independent of each other. We will discuss the viewpoints independently<br />
from each other rst. Thereafter their inter-relationship will be<br />
discussed.
4.1. Modelling Layers 43<br />
Func1<br />
Func3<br />
Func4<br />
Func2<br />
Func5<br />
Requirements<br />
Functionality Mapping<br />
T(F1)<br />
T(F3)<br />
T(F2)<br />
T(F4)<br />
T(F5)<br />
MethodA<br />
MethodB<br />
MethodC<br />
MethodD<br />
Object<br />
Figure 4.5: Conceptual Model of <strong>Layering</strong><br />
Object functionalities that are present in the requirements must one way or<br />
the other be represented in the object model. This can be done by mapping<br />
the functionalities to parts of the object model. This divides the layering model<br />
into three di erent parts:<br />
Functionalities<br />
Transformations<br />
Methods<br />
As can be seen in Figure 4.5, these transformations can manifest themselves in<br />
several ways. It is possible that<br />
1. One functionality transforms to one method (T F1 );<br />
2. A functionality transforms to a couple of methods (T F2 );<br />
3. Some functionalities transform to one <strong>and</strong> the same method (T F3 <strong>and</strong> T F4 );<br />
4. A functionality does not transform to a method, but instead has some<br />
e ect on the object as a whole (T F5 ).<br />
Here, TF1 is the simplest transformation. It directly maps a functionality<br />
to an object method. Note that functionalities <strong>and</strong> methods can exist in any<br />
granularity. Therefore, transformation TF2 can occur, where some coarse grained<br />
functionality maps to several ne grained methods. These two cases are the same<br />
for us, so we will use either one.<br />
When two (or more) functionalities map to the same object method, we<br />
have transformations TF3 <strong>and</strong> TF4 . If this is the case, we cannot use functionality<br />
F3 <strong>and</strong> F4 independently from each other. Nonetheless, they are (probably)<br />
independent functionalities. In this situation, often one of the two functionalities<br />
maps directly to the method, as in TF1 , while the other maps indirectly to the<br />
method, thus in fact being a side e ect of the normal functionality.
44 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
Object versus Meta Level <strong>Layering</strong><br />
Functionality can be object level or meta level functionality. We de ne functionality<br />
as object level, when all information necessary for the functionality<br />
is present at the object level. Besides this, the functionality must directly be<br />
mapped to a method representing exactly that functionality, instead of being<br />
some side-e ect of another method representing some functionality. All other<br />
functionalities are de ned to be at the meta level.<br />
Object Level <strong>Layering</strong> Object level layering is the most commonly used way of<br />
layering. The existing functionality of objects is modi ed or extended by adding<br />
layers to the objects. Object level layering comes in two avours.<br />
Inheritance Normally, when class libraries are designed, the top level<br />
classes are the most abstract, <strong>and</strong> de ne layers <strong>with</strong> most of the basic functionality.<br />
The leaf classes of a class tree are very speci c, <strong>and</strong> de ne operations that<br />
make use of the basic functionalities of the \root" classes. When a class must be<br />
adapted or extended for a certain reason, a subclass is created which overrides<br />
or extends the default behaviour. In layer terms, an extra layer is added to the<br />
objects which implements the wanted behaviour.<br />
Delegation A less-known version of object level layering is delegation.<br />
With delegation, the classes are not connected by sub-superclass relations. An<br />
object encapsulates an internal object, to which some functionalities are delegated.<br />
With this mechanism it is also possible to hide some or all the functionalities<br />
of the encapsulated object. In this case, delegation resembles a part-of<br />
relationship.<br />
Lieberman (1986) evaluates <strong>and</strong> compares both implementations of object<br />
level layering, <strong>and</strong> concludes that delegation is a richer mechanism. This<br />
conclusion is based on the fact that inheritance can be simulated <strong>with</strong> delegation,<br />
while it is impossible to simulate delegation <strong>with</strong> inheritance.<br />
Meta Level <strong>Layering</strong> With meta level layering, layers are constructed by reifying<br />
elements of object systems. Object systems are constructed <strong>with</strong> objects <strong>and</strong><br />
messages. Theoretically, both elements can be rei ed, which means that information<br />
about the element itself is made available as a rst class object.<br />
Re ection-based layering, as meta level layering can also be called, is<br />
discussed in detail by Ferber (1989). He identi es three re ection mechanisms.<br />
Class-Based Re ection All objects of a certain class have the common<br />
meta-object, which is the class, attached to it. This meta-object implements<br />
the method dispatch function dependent on the desired behaviour. All objects<br />
of some class have the same behaviour then.
4.1. Modelling Layers 45<br />
Object-Based Re ection In object-based re ection, all objects have a<br />
potential meta-object attached to it. This meta-object is not the class of the<br />
object, neither do objects share meta-objects.<br />
Re ection of the Communication Process When the messages that are<br />
sent in the system are all instances of class Message, we have an explicit<br />
re ection of the communication process. When speci c behaviour is desired<br />
then, a subclass of Message can be de ned, which implements this behaviour.<br />
Static versus Dynamic <strong>Layering</strong><br />
Until now, we only discussed layers as being chunks of object speci cations that<br />
can be attached to objects. We did not discuss how they can be attached to<br />
objects.<br />
Static <strong>Layering</strong> With static layering, one or more layers are bound to classes<br />
at compile time. This means that, after the program is build, it is impossible<br />
to change the layering of the objects in the system.<br />
This is a big problem in software engineering. When a system evolves, the<br />
number of functionalities that objects must support grows steadily. Often, large<br />
parts of objects are only necessary for a short period of time, or are only used<br />
by speci c parts of the system. This is especially the case <strong>with</strong> role playing. It<br />
is impossible to foresee all future roles for all individual objects. Also, we get a<br />
lot of classes that only exist because of the combination of roles <strong>and</strong>/or features<br />
of objects. Consider for example a class Person <strong>and</strong> the roles Employee <strong>and</strong><br />
Manager. We must de ne the classes Person, Employee, Manager <strong>and</strong><br />
EmployeeAndManager to support all possible combinations.<br />
Now suppose we also de ne a property called Barking, which de nes<br />
that a barking sound is produced <strong>with</strong> every method invocation. The we must<br />
de ne four new classes: BarkingPerson, BarkingEmployee, Barking-<br />
Manager <strong>and</strong> BarkingEmployeeAndManager. One can see that this gets<br />
worse <strong>with</strong> every new role or property we add.<br />
Figure 4.6 shows the described situation. To create a Person who is at the<br />
same time Employee <strong>and</strong> Manager, <strong>and</strong> who also must bark, we must create<br />
the appropriate class BarkingEmployeeAndManager which incorporates<br />
all wanted properties.<br />
There is another drawback <strong>with</strong> this construction. It is not possible to<br />
switch from one role to the other <strong>with</strong>out losing object identity. Note that,<br />
independent of the current role of a Person, he or she will always remain a<br />
Person (Wieringa <strong>and</strong> Jonge 1991a, Wieringa <strong>and</strong> Jonge 1991b). With our<br />
example, it is not possible to remove the Barking property, or to replace the<br />
Manager property <strong>with</strong> something like Director.
46 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
Person<br />
Barking<br />
Employee Manager BarkingPerson<br />
EmployeeAndManager<br />
BarkingEmployeeAndManager<br />
aBarkingEmployeeAndManager<br />
Figure 4.6: Static layering generates complex class structures<br />
Dynamic <strong>Layering</strong> The problems <strong>with</strong> static layering disappear when we use<br />
dynamic layering. In this case, we de ne the layers more or less independent<br />
from each other, <strong>and</strong> attach the appropriate layers to the objects at runtime.<br />
So in our example, we de ne an object class Person, <strong>and</strong> three individual<br />
classes Employee, Manager <strong>and</strong> Barking. Now, when we have a Person<br />
who becomes a Manager, we attach a Manager layer to the Person object. If<br />
we then want this Manager to start barking, we attach aBarking layer to it.<br />
In Figure 4.7, we see the same situation as in Figure 4.6, but now <strong>with</strong><br />
dynamic layering. We can see that the class structure is much simpler now.<br />
Moreover, it is very easy to extend the class structure <strong>with</strong> additional roles <strong>and</strong><br />
properties. This mechanism closely re ects Object Composition.<br />
What Can We Do <strong>with</strong> Dynamic <strong>Layering</strong>? Dynamic layering enables us to<br />
manipulate object behaviour <strong>and</strong> structures at runtime. With this technique,<br />
we can do interesting things.<br />
Dynamic Role Playing We can explicitly distinguish between objects<br />
<strong>and</strong> the roles they must play. When carefully designed, it is very easy to congure<br />
an object <strong>with</strong> certain roles, <strong>and</strong> add others later. It is also possible to<br />
de ne new roles at a later stage, <strong>with</strong>out rede ning other object speci cations.
4.1. Modelling Layers 47<br />
Person EmployeeRole BarkingProperty<br />
ManagerRole<br />
aPerson<br />
anEmployeeRole<br />
aManagerRole<br />
aBarkingProperty<br />
Figure 4.7: Dynamic layering keeps class structures simple<br />
Behaviour Injection We can add new behaviour to, or recon gure existing<br />
behaviour of any object. We can de ne subsystem-speci c behaviour separately<br />
from the original object, clearly distinguishing between the intrinsic<br />
features of an object that is stored in the class itself, <strong>and</strong> the extrinsic features<br />
of an object that is stored in the layers (Minsky <strong>and</strong> Pal 1995).<br />
Protocol Injection <strong>and</strong> Conformance When two or more objects must<br />
communicate, they must conform to some protocol. Normally, when these objects<br />
are not designed that way, their speci cations must be rewritten or extended,<br />
introducing a lot of problems <strong>and</strong> sources for problems. With dynamic<br />
layering, we can let objects \explain" their own protocol to communication c<strong>and</strong>idates<br />
by injecting their own protocol into these c<strong>and</strong>idate objects. This way,<br />
we prevent enormous object speci cations consisting of many protocols. All protocol<br />
speci cations are de ned separately, which makes using <strong>and</strong> maintaining<br />
these protocols much easier.<br />
Separate Behaviour from Control Often, a layer can be divided into behaviour<br />
<strong>and</strong> control of that behaviour. Think for example of a layer that records<br />
history information. Next to the actual recording <strong>and</strong> displaying of history information,<br />
it is possible to provide control functions like starting, stopping <strong>and</strong><br />
clearing of history information. Because we represent layers as rst-class objects<br />
<strong>with</strong> dynamic layering, it is possible to record history information from one object,<br />
while we control history recording from another object, like in Figure 4.8.
48 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
Obj1 Obj2<br />
HistoryRecorder HistoryRecorder<br />
Operator<br />
HistoryControls<br />
Figure 4.8: Separate Behaviour from Control: History recording of objects Obj1<br />
<strong>and</strong> Obj2 is controlled by anOperator<br />
Coordinated Behaviour Until now we assumed that the dynamic layer<br />
resided somewhere inside the target object. The layer can reside somewhere outside<br />
the object too however. We have already seen this in Figure 4.8. In (Aksit<br />
et al. 1993), this phenomenon is discussed in more detail, although dynamic<br />
attachment is not addressed.<br />
The paper gives an example of coordinated behaviour using a de ned<br />
ReferencePoint class. <strong>Objects</strong> of this class are constrained by some Figure<br />
object, which ensures that ReferencePoints do not extend the gure's boundaries.<br />
The constraint is hard-coded in the de nition of the ReferencePoint<br />
however, which prevents the class from being reused when other or none of such<br />
constraints apply. In fact the constraint is only valid in the context of a Figure<br />
object. With dynamic layering, we can model this more precisely, resulting in<br />
models that are more exible.<br />
Single Public versus <strong>Multiple</strong> Private Properties Object properties often<br />
apply to the object in general, which means that the property more or less<br />
is visible to all potential client objects. Sometimes however, object properties<br />
purely exist because client objects assign these properties to the server object.<br />
In the real world, this happens all the time.<br />
A good example are sweet names. When person A assigns a sweet name<br />
to person D, the sweet name belongs to person D, but is only visible to person<br />
A. The sweet name is a property private to person A. Maybe some person C<br />
also has assigned a (di erent) sweet name to person D. This can <strong>and</strong> may not<br />
a ect the sweet name of person A. Now (lucky guy) person D has two properties<br />
SweetName. Figure 4.9 shows this situation, where Person A <strong>and</strong> C have private<br />
sweet names for person D, <strong>and</strong> person B has no sweet name at all for person D.<br />
We can use this feature in software models, where objects often have<br />
some properties especially for some subsystem. With dynamic layering, we can
4.1. Modelling Layers 49<br />
Person A<br />
SweetName<br />
Person B<br />
Person D<br />
SweetName<br />
Person C<br />
Figure 4.9: <strong>Multiple</strong> Private Properties assigned to one single object<br />
model this simply, <strong>with</strong>out polluting the software model <strong>with</strong> elements that are<br />
almost never used.<br />
Interrelationship between the Viewpoints of the Model<br />
How do the di erent viewpoints of the model relate to each other? The functionality<br />
view focuses on the semantics of the real world. This results in objectlevel<br />
or meta-level layering, which expresses semantics of the object model. This<br />
model can be implemented in a static or a dynamic way.<br />
In the next section, we will describe a scenario, where functionality changes will<br />
result in object- <strong>and</strong>/or meta level layers.<br />
4.1.3 Scenario of Changes<br />
In this section, we will focus on the impact of the various transformations on<br />
the software model that represent the requirements. This scenario is based on<br />
the functionality mapping viewpoint. We will see that some functionalities are<br />
at the object level, while others transform to meta level layers.<br />
When manipulating functionalities, the following changes are possible,<br />
where the transformations refer to Figure 4.5:<br />
Add methods (T F1 <strong>and</strong> T F2 );<br />
Rede ne methods (also T F1 <strong>and</strong> T F2 );<br />
Extend methods (one of T F3 <strong>and</strong> T F4 );<br />
Add object-orthogonal behaviour (T F1 ).<br />
These operations can occur inside every layer. We can also de ne operations on<br />
layers themselves:<br />
Add Layer;<br />
Remove Layer;<br />
Compose object <strong>with</strong> several layers.<br />
These operations are only meaningful when we use dynamic layering. First, this<br />
section only focuses on static layering. After that, we repeat the scenario in one<br />
step using dynamic layering.
50 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
Add Methods<br />
When we want to add methods to an object using a layer, we are adding functionality<br />
to the object using transformation TF1 of Figure 4.5. It is also possible<br />
that we complete already existing functionality by providing appropriate definitions<br />
of abstract methods, or de ne new abstract functionalities by de ning<br />
\incomplete" methods (For example Pree's (1994) template <strong>and</strong> hook methods).<br />
Rede ne Methods<br />
Often, the addition of a functionality required changes to the de nitions of other<br />
functionalities. This means that the appropriate methods have to be rewritten.<br />
This can be done in two di erent ways:<br />
1. rede nition;<br />
2. extension.<br />
Rede nition of the method means that the original de nition is not being used<br />
anymore. This is often seen as an encapsulation violation, because complete<br />
rede nition requires detailed knowledge of the target object.<br />
When the original de nition is used, we in fact extend the original de -<br />
nition. We will see an example of this in the next section. Note that this form of<br />
method extension is not called this way any further, because we de ne method<br />
extension as described next.<br />
Extend Methods<br />
When we add functionalities, but attach them to already existing methods, we<br />
call this method extension. We refer to transformation TF3 <strong>and</strong> TF4 of Figure 4.5.<br />
One of these functionalities represents the already existing method. The other<br />
one will be added in a new layer. Because this new functionality will be a<br />
side e ect of the method, we discuss this separately from the extended method<br />
rede nition mentioned above.<br />
Add Object-Orthogonal Behaviour<br />
If the functionality that we want to add is not speci c for the target object, we<br />
follow transformation TF5 of Figure 4.5. The functionality will in principle be a<br />
side e ect of all methods of the target object.<br />
Dynamic <strong>Layering</strong><br />
We mentioned three operations on layers at the beginning of this section:<br />
Add Layer;<br />
Remove Layer;<br />
Compose object <strong>with</strong> several layers.<br />
Because removing a layer is in fact the reverse of adding <strong>and</strong> composing layers,<br />
there is nothing special <strong>with</strong> it, besides the possibility of invalidating other<br />
layers that depend on the removed layer. We will not discuss the removal of<br />
layers here.
4.2. C ++ implementation 51<br />
Object<br />
Legend<br />
User Mail MailH<strong>and</strong>ler<br />
HUser HeadingMail<br />
AUser AttachmentMail<br />
MVUser UserSystemViewMail<br />
RNUser ReadNotificationMail<br />
HisUser<br />
Normal class<br />
Normal class (<strong>with</strong> overhead)<br />
Overhead class<br />
HistoryMail<br />
Figure 4.10: <strong>Layering</strong> Scenario<br />
MVMailH<strong>and</strong>ler<br />
Add Methods<br />
Redefine Methods<br />
Prepare for Extend Methods<br />
Extend Methods<br />
Add Object-Orthogonal Behaviour<br />
The best way of showing how layers can be added to a target object,<br />
<strong>and</strong> composed through dynamic layering, is de ning the same layers as in the<br />
previous sections, <strong>and</strong> attach them to the target object at runtime.<br />
4.2 C++ implementation<br />
In this section, we will discuss the C ++ implementation of the scenario discussed<br />
in Section 4.1.3. We will start <strong>with</strong> a Simple Mail System, as described in<br />
Section 3.2.1. The rest of the scenario is depicted in Figure 4.10.<br />
4.2.1 Add Methods: Heading Mail System<br />
In this section, we extend the MailMessage <strong>with</strong> a heading. We will use this<br />
heading for textual representation of information about the MailMessage itself,<br />
apart from the body of course.<br />
Scenario direction
52 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
char<br />
HeadingMail::getMailAsText(void)<br />
f<br />
:::;<br />
c this!getMailContents();<br />
h this!getMailHeading();<br />
:::;<br />
return r;<br />
g<br />
Motivation<br />
Figure 4.11: Never access \lower level" structures directly<br />
MailMessages are presented to the User <strong>with</strong> special mail readers. These readers<br />
normally construct a header containing certain information about the MailMessage<br />
itself, like the MailOriginator <strong>and</strong> the MailReceiver. In this section, we discuss<br />
the implementation of a HeadingMail, which is capable of constructing<br />
such a header.<br />
Semantic Structure<br />
The functionality that this layer provides is, at least in the static implementation,<br />
2 very simple. The transformation of this functionality isoftype T F1 .<br />
We must be prepared to future adaptations however, <strong>and</strong> never manipulate<br />
nor access internal structures of the target object directly. Ifwe do this,<br />
we can never adapt the \behaviour" of the internal structures in another layer<br />
later. We will show that it is important to use a certain coding convention in<br />
order to achieve maximum exibility.<br />
Implementation Consequences<br />
In the implementation, we have to con rm to certain coding principles to avoid<br />
breaking reusability. Johnson <strong>and</strong> Foote (1988) give us several guidelines to<br />
create class structures that are reusable. Later, Lieberherr <strong>and</strong> Holl<strong>and</strong> (1989)<br />
describe the Law of Demeter, which goes further <strong>and</strong> dictates some independence<br />
rules by law.<br />
To decouple the classes Mail <strong>and</strong> HeadingMail as much as possible,<br />
all references to the instance variables is implemented by sending messages to<br />
this, which inC ++ st<strong>and</strong>s for the receiver of the message (See Figure 4.11).<br />
In HeadingMail two methods are de ned, called getMailHeading <strong>and</strong><br />
getMailAsText. getMailHeading returns a textual presententation of the heading<br />
information, while getMailAsText returns a complete textual representation of<br />
the MailMessage, in fact combining the header <strong>with</strong> the contents. Appendix C.1<br />
2. See Section 4.2.5 for a discussion about the dynamic implementation
4.2. C ++ implementation 53<br />
lists the complete C ++ implementation. Note the this reference calls in the<br />
methods as in Figure 4.11.<br />
4.2.2 Rede ne Methods: Attachment Mail System<br />
In this section, we extend the mail system by allowing the User to attach les<br />
to the MailMessage.<br />
Motivation<br />
Sometimes, a textual MailMessage should be accompanied by extra documents,<br />
like enclosures <strong>with</strong> a letter. These are called attachments, <strong>and</strong> in this section<br />
we are going to de ne class AttachmentMail, which is capable of storing <strong>and</strong><br />
sending Attachments accompanied <strong>with</strong> a MailMessage.<br />
Semantic Structure<br />
By adding this functionality, we have to rede ne the heading de nition provided<br />
in HeadingMail. If there is an Attachment present, we must include<br />
information about it in the mail header. Note that the existing header should<br />
not be touched, we only want toadd something to it.<br />
Implementation Consequences<br />
In this scenario step, we add the functionality of attachments to the Mail-<br />
Message. Therefore we de ne a separate Attachment class to hold the actual<br />
attachment. Besides this, the Attachment must be placed into the MailMessage.<br />
We de ne methods setMailAttachment <strong>and</strong> getMailAttachment for this task.<br />
For the rede nition of the mail header, we override the getMailHeading<br />
method. It calls the original getMailHeading, <strong>and</strong> adds a line about the attachment<br />
to it, like in Figure 4.12. Note that if there is no attachment present, the<br />
extra functionality is skipped, as if the method did not exist. We will show a<br />
much neater implementation using dynamic layering in Section 4.2.5. In this dynamic<br />
implementation, the attachment functionality <strong>and</strong> the rede ned header<br />
are de ned in the separate attachment-layer, which can be connected to the<br />
Mail object at runtime, causing no overhead at all when no attachments are<br />
used.<br />
4.2.3 Extend Methods: ReadNoti cation Mail System<br />
In this section we implement a scheme for transparent noti cation of a Mail-<br />
Message read to the MailOriginator.<br />
Motivation<br />
If important or time-critical MailMessages are sent by mail, the MailOriginator<br />
wants to know when the MailReceiver has read the message. This of course has<br />
to be transparent to the MailReceiver.
54 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
char<br />
AttachmentMail::getMailHeading(void)<br />
f<br />
:::;<br />
h HeadingMail::getMailHeading();<br />
if ( attachment NULL) f<br />
== Use original de nition<br />
s h;<br />
g else f<br />
== Extend heading <strong>with</strong> attachment ref<br />
s h+:::;<br />
g<br />
return s;<br />
g<br />
Figure 4.12: Rede ned methods basically extending functionality must call the<br />
original method, <strong>and</strong> often are conditional in their extension<br />
Semantic Structure<br />
This functionality has the important property that it is transparent to the user.<br />
This means that it also must not be re ected in the interface of the object. This<br />
functionality should be implemented in such away that the calling environment<br />
does not have to be adapted to enable read noti cation.<br />
This means that the functionality must be implemented in the getMail-<br />
Contents method, which is the only place where we can detect that a MailMessage<br />
is being read. Now we have situation TF3 =TF4 from Figure 4.5, where we<br />
have two functionalities, namely read mail <strong>and</strong> automatic read noti cation,<br />
combined into one method, namely getMailContents.<br />
In order to make the program adaptable, we must one way or the other<br />
separate the two functionalities in the implementation. Only then will it be<br />
possible to rede ne the two functionalities independently of each other.<br />
Implementation Consequences<br />
In fact, we do not only want the functionality to be invisible in the interface,<br />
we also want ittobeinvisible in the (normal) implementation of the object.<br />
This causes the functionality to result into a meta layer. It \st<strong>and</strong>s<br />
above" the normal execution of the program, more or less extending method<br />
execution semantics for one particular method. This is done by pre xing the<br />
actual method execution by generating a reply containing a read noti cation to<br />
the MailOriginator.<br />
We can only detect the invocation of getMailContents inside the method<br />
itself. We therefore separate invocation <strong>and</strong> execution into two methods get-<br />
MailContents <strong>and</strong> pureGetMailContents, using the same mechanism as we did
4.2. C ++ implementation 55<br />
char<br />
ReadNoti cationMail::getMailContents(Object sender)<br />
f<br />
if (this!senderIsReceiverAndMustNotify(sender))<br />
this!notify();<br />
return UserSystemViewMail::getMailContents(sender);<br />
g<br />
Figure 4.13: Separate Mail Read <strong>and</strong> Send ReadNoti cation functionalities<br />
for implementing multiple views. This way, we separate the two functionalities<br />
into two methods (pureGetMailContents <strong>and</strong> sendReadNoti cation), <strong>and</strong> couple<br />
them in the message invocation method getMailContents (See Figure 4.13 for a<br />
coding extract of Appendix C.3). We can see in Figure 4.10, that we reused the<br />
coding scheme we introduced in Section 3.2.2. Therefore we did not de ne the<br />
pureGetMailContents method, <strong>and</strong> also did not call it from the getMailContents<br />
method from Figure 4.8. If we had done this, we had ignored other method<br />
entry semantics (like the views of UserSystemViewMail.).<br />
4.2.4 Add Object-Orthogonal Behaviour: History Mail System<br />
We now add the recording of historical information about message sends to our<br />
mail system.<br />
Motivation<br />
We want to keep track of what objects sent what methods to which target<br />
objects at what time. Wewant this for debugging our ReadNotificationMail<br />
implementation for example.<br />
Semantic Structure<br />
This scenario step corresponds <strong>with</strong> transformation TF5 of Figure 4.5. We add<br />
functionality that has an e ect on the complete object. Of course we do not<br />
want to record history information in the methods themselves, because adding<br />
or rede ning methods in subclasses would require new explicit history recording<br />
code. Further, history recording is st<strong>and</strong>ing \above" normal method execution,<br />
resulting in a meta layer, just as <strong>with</strong> the ReadNotificationMail class.<br />
We also want meta-information in our history report, namely the name<br />
of the methods that are invoked. If the computational model does not provide<br />
this information, we must work around this problem.<br />
Implementation Consequences<br />
To implement this functionality in a composable way, wehave to use the same<br />
implementation scheme as in the ReadNotificationMail class. There is one
56 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
void<br />
HistoryMail::setMailReceiver(Object sender,MVUser user)<br />
f<br />
this!doMeta("setMailReceiver",sender);<br />
ReadNoti cationMail::setMailReceiver(sender,user);<br />
g<br />
Figure 4.14: Every method has to be rede ned to implement history information<br />
recording<br />
big di erence however. In HistoryMail, we must adapt the behaviour of all<br />
methods, instead of just one. Therefore, we must rede ne all interface methods<br />
of the mail class, <strong>and</strong> add history information recording code to it.<br />
In Figure 4.14 we can see one of all methods that had to be (re-)de ned<br />
to implement HistoryMail. The problem here is essentially the same as the introduction<br />
of Warning2Mail in Section 3.2.6. There we also had to de ne the<br />
same functionality for a set of methods (although the functionality inWarning2Mail<br />
was limited to four methods). If in some subclass a new method is<br />
introduced, the history recording code must explicitly be de ned for the new<br />
method then.<br />
We can see another analogy between Warning2Mail <strong>and</strong> History-<br />
Mail. Both need to know which method is currently active. This information<br />
is not explicitly available, <strong>and</strong> thus we must provide this information ourselves.<br />
4.2.5 Dynamic <strong>Layering</strong>: Dynamic Mail System<br />
We repeat two scenario steps from the previous sections using dynamic layering<br />
now.<br />
Motivation<br />
Until now, we have enhanced the mail system <strong>with</strong> several functionalities. The<br />
problem is, that all these enhancements have to be known <strong>and</strong> speci ed prior<br />
to using the mail system. Therefore, we want to implement a DynamicMail<br />
system, which is capable of including any possible enhancement which we can<br />
think of in the future.<br />
Semantic Structure<br />
The semantic structure of the dynamic mail system is completely di erent from<br />
those we have already seen. The structure must be capable of h<strong>and</strong>ling all<br />
possible transformations from Figure 4.5.<br />
This can be done by de ning a generic layer that can be added to the<br />
target object at runtime. Di erent layers <strong>with</strong> di erent functionalities can be<br />
implemented upon this generic layer, <strong>and</strong> then be tted to the target object<br />
when appropriate.
4.3. Conclusions 57<br />
Implementation Consequences<br />
The GoF book (Gamma et al. 1995) identi es this structure as the Decorator<br />
pattern. By using this pattern it is possible to add behaviour to an object at<br />
run-time. The pattern has several drawbacks however. The book itself mentions<br />
(amongst others) the object-identity problem. The decorated object has not<br />
the same object-identity as the original object. Of course this is an undesired<br />
situation.<br />
A drawback of using this pattern which is not mentioned in the book<br />
is the following. In the implementation of the DynamicMail, we have the<br />
same problem as in HistoryMail, as we have no way of uniformly modify<br />
the behaviour of all methods. This means, that we have to re-implement all<br />
methods again for meta-level layers.<br />
The interface conformance requirement has important drawbacks on the<br />
exibility of the pattern. For example, meta-level layers can only operate on<br />
the small interface de ned by the abstract Component class. Also, layers are<br />
incapable of adding functionalities to the object, when they need to add methods<br />
to the class for it (which would require us to rewrite class speci cations, which<br />
violates the reusability requirement of an object model).<br />
The Decorator pattern requires us to write a lot of overhead code.<br />
Look for example at Figure 4.15. We can see that one simple function takes<br />
three declarations to work. Also, for each meta-level layer, we have to specify<br />
all methods again. Another drawback here is, that the MailHistory is not<br />
reusable as a generic HistoryReporter.<br />
4.3 Conclusions<br />
In this chapter we de ned a model for object layering. We also showed how<br />
several aspects in this model could change, <strong>and</strong> how this could be implemented<br />
in a language like C ++.<br />
It appears that static object-level layering is very straightforward in C ++.<br />
Meta-level layering is much more problematic, mainly because this cannot be<br />
done orthogonally. The problem base is the same as <strong>Multiple</strong> <strong>Views</strong>. In Section<br />
3.3 we also identi ed problems because of the lack of static as well as<br />
dynamic meta information, <strong>and</strong> the absence of a single message entry point in<br />
objects, which prevents us to model orthogonal behaviour like inHistoryMail<br />
in a proper way.<br />
Dynamic layering is also very problematic. The Decorator pattern<br />
can be used sometimes, but this pattern has important drawbacks, like identity<br />
problem <strong>and</strong> interface conformance, which prevents a decorator participant from<br />
being reused.
58 Chapter 4. Modelling Issue: <strong>Layering</strong><br />
class MailComponent f<br />
:::;<br />
virtual void send();<br />
:::;<br />
g<br />
class DynamicMail : public MailComponent f<br />
:::;<br />
virtual void send() f printf("The actual method here..."); g<br />
:::;<br />
g<br />
class MailDecorator : public MailComponent f<br />
MailDecoratorfMailComponent pg fcomponent p; g<br />
:::;<br />
virtual void send() f component!send(); g<br />
:::;<br />
private:<br />
MailComponent component;<br />
g<br />
class MailHistory : public MailDecorator f<br />
:::;<br />
virtual void send() f printf("Do some meta work");<br />
MailDecorator::send(); g<br />
:::;<br />
g<br />
Figure 4.15: C ++ example of one simple function in a Decorator pattern
4.3. Conclusions 59<br />
Smalltalk implementation<br />
We did not give the example code in Smalltalk, but we will give some hints<br />
about it here.<br />
For meta-level layering, the same remarks apply here as we have given<br />
for <strong>Multiple</strong> <strong>Views</strong>. For dynamic layering, we can address the following issues,<br />
based on the Decorator pattern.<br />
Identity problem Smalltalk has a method called become:, which at runtime<br />
shifts an object to another class. With this mechanism, the identity problem<br />
could be eliminated.<br />
Interface conformance In Smalltalk, we can use the doesNotUnderst<strong>and</strong> mechanism<br />
to automatically forward incoming methods to next layers (<strong>and</strong> eventually<br />
to the target object).
60 Chapter 4. Modelling Issue: <strong>Layering</strong>
Chapter 5<br />
Composition Filters Solutions for the Modelling<br />
Issues<br />
In this chapter we will describe the solutions for the examples from Chapters 3<br />
<strong>and</strong> 4 in the Composition Filters Object Model. In Section 1.1, we mentioned<br />
the language Sina that supports this model. In Section 2.1 we already discussed<br />
the model. Because we use Sina in this chapter for implementing the examples,<br />
we will rst brie y introduce some features <strong>and</strong> caveats of the language in<br />
Section 5.1. Then, in Sections 5.2 <strong>and</strong> 5.3 we discuss the Sina implementation<br />
of <strong>Multiple</strong> <strong>Views</strong> <strong>and</strong> <strong>Layering</strong> respectively. The corresponding full-text code<br />
listings are in Appendices B <strong>and</strong> D.<br />
5.1 The Sina Language<br />
This section is based on Koopmans (1996).<br />
In this section, we will brie y discuss the Sina language, <strong>with</strong> respect to the<br />
Composition Filters Object Model. This chapter implements techniques for<br />
<strong>Multiple</strong> <strong>Views</strong> <strong>and</strong> Object <strong>Layering</strong> in the Composition Filters Object Model,<br />
using the Sina language. We will discuss some problems <strong>with</strong> the language in<br />
this section.<br />
Sina is implemented in a multi-threaded environment. This means that a program<br />
can have more than one active object at some point in time. To prevent<br />
problems <strong>with</strong> this, the Sina compiler defaults to st<strong>and</strong>ard single-threaded objects,<br />
which in turn means that <strong>with</strong>in one single object, there will only be<br />
one thread active. When a method is executed in an object, all other incoming<br />
messages are blocked until the executing method has nished. We will see<br />
some problems <strong>with</strong> this feature, because objects can ask information from each<br />
other, resulting in deadlock situations as in Figure 5.1 on page 63, which will<br />
be explained in the next section.<br />
Another problem is that Sina does not implement a meta object model,<br />
like Smalltalk does. There is some rudimentary implementation available, but<br />
61
62 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
this is not very usefull now. This is related to some problems <strong>with</strong> the Composition<br />
Filters Object Model however, because we do not know when to identify<br />
two object as members of the same \class" yet (mainly because objects can<br />
change dramatically during their lifetime, see dynamic layering for example).<br />
5.2 <strong>Multiple</strong> <strong>Views</strong><br />
In this section, we will show the Composition Filters solution of the <strong>Multiple</strong><br />
<strong>Views</strong> problem. We will follow the same scenario we used in Chapter 3, <strong>and</strong><br />
compare the Composition Filters solution <strong>with</strong> the C ++ solution from Chapter 3.<br />
5.2.1 Simple Mail System<br />
In the implementation of the MailH<strong>and</strong>ler class, there is a di erence <strong>with</strong><br />
the C ++ implementation. Although we did not mention it in Chapter 3, the C ++<br />
class MailH<strong>and</strong>ler was constructed according to the Singleton pattern. 1<br />
In short, this pattern is used to enforce that only one instance of some class<br />
exists. Because the Composition Filters Object Model lacks an interface to<br />
instance creation primitives, it is not possible to control these primitives <strong>with</strong>,<br />
for example, views. So, in Sina we cannot implement the Singleton pattern.<br />
There is another problem <strong>with</strong> the MailH<strong>and</strong>ler class. Note the early<br />
return in the body of send. The default behaviour of a method prevents multiple<br />
execution threads in an object. This statement prevents a deadlock in the<br />
MailH<strong>and</strong>ler, because the MailMessage will print the name of the MailH<strong>and</strong>ler<br />
through the getName method, which will be delayed until the send message<br />
has terminated. See Figure 5.1 how the deadlock situation emerges. The Sina<br />
reference manual (Koopmans 1996, Chapter 10) warns for this situation. The<br />
warning dictates not to send any messages to self or server from a condition.<br />
In this Mail System there is a similar situation, where the MailMessage asks<br />
the MailH<strong>and</strong>ler to deliver it to the MailReceiver.<br />
In the User class, we introduce an early return statement in the receive method<br />
too, for the same reason as mentioned above. Because the Singleton pattern<br />
cannot be implemented in Sina, we access the global MailH<strong>and</strong>ler object in the<br />
Mail class through an external variable.<br />
The rest of the implementation is rather trivial. It closely resembles the<br />
implementation of the C ++ solution.<br />
5.2.2 Add <strong>Views</strong>: UserSystemView Mail System<br />
In this section we discuss the implementation of views in Sina. We can see how<br />
easy it is to support view semantics in this language, because the properties that<br />
we need to support views are part of the language model. Note that only the<br />
1. The Singleton pattern is discussed in (Gamma et al. 1995)
5.2. <strong>Multiple</strong> <strong>Views</strong> 63<br />
MailH<strong>and</strong>ler MailReceiver<br />
receive<br />
DEADLOCK<br />
getName<br />
send receive<br />
Figure 5.1: Deadlock ofsend message in the MailH<strong>and</strong>ler<br />
Mail class needs to be updated to support views. The User class is subclassed<br />
only to implement another test method that uses the new UserSystemView-<br />
Mail class.<br />
The UserSystemViewMail class declares the two views userView <strong>and</strong><br />
systemView, <strong>and</strong> couples the views to the methods <strong>with</strong> lter expressions. These<br />
lter expressions accept incoming messages when the condition (view) is true<br />
<strong>and</strong> the method selector matches. When the method selector matches, but the<br />
view is not active, an error is raised (because of the Error lter that is used).<br />
The match between the view model from Section 3.1.2 <strong>and</strong> the Composition<br />
Filters Object Model is as follows. The method set M o is not changed in the<br />
view model. In this section we only add views, so the method set in the Sina<br />
implementation is not changed either. We can see this in the implementation of<br />
UserSystemViewMail, where we inherit from the Mail class, <strong>and</strong> therefore<br />
do not have to rede ne any features from the class Mail. We do have to de ne<br />
the views <strong>and</strong> the method-view mappings here.<br />
View De nitions<br />
Normally, view de nitions are rather trivial. We will see this in the next sections,<br />
where we will de ne some easy-to-implement views. The views userView <strong>and</strong><br />
systemView however are not easy to implement, because we want to restrict<br />
access to objects of the classes User <strong>and</strong> MailH<strong>and</strong>ler <strong>and</strong> their subclasses<br />
respectively. The Sina language does not support a meta-object or classes as<br />
objects. Therefore it is not simply possible to ask a Sina object for its type. It
64 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
View Method OK<br />
View Method p<br />
:View Method<br />
View :Method p<br />
:View :Method p<br />
Table 5.1: Possible mappings between methods <strong>and</strong> views<br />
is even more di cult to determine any type-subtype relations, because of the<br />
dynamic behaviour of Sina class interfaces. In our implementation we used the<br />
isKindOf method, a method which in fact is not available.<br />
Method-View Mapping Semantics<br />
For a better underst<strong>and</strong>ing on how a view is implemented <strong>with</strong> a lter expression,<br />
we will rst elaborate on what lters do <strong>with</strong> messages.<br />
For simplicity, we restrict to the situation where we need the mapping<br />
between one view <strong>and</strong> one method. In Table 5.1, we see the four possible actual<br />
situations for a message. The rst means that the view is active, <strong>and</strong> that the<br />
listed method is called. In Table 5.1 we also see that this is OK, which means<br />
that the method is allowed to be executed. When the method is called, but the<br />
view is not active, we want to raise an error. For the other two situations, we<br />
see that when another method is called, we are not interested in this situation,<br />
so we accept this.<br />
The lter expression that implements this behaviour, thus has to exclude<br />
the \bad" situations from Table 5.1. All other situations have to be accepted.<br />
Because of the semantics of a lter expression, we have to construct a<br />
lter expression that shows what is allowed in a message pattern instead of what<br />
is not allowed. 2 Bergmans (1994) also recognises this problem. So in order to<br />
realise the values from Table 5.1, we list the three OK values from this table.<br />
The remaining situation(s) will not match the lter expression <strong>and</strong> thus will<br />
raise an error in the error lter. See Figure 5.2 for an example listing of a class<br />
<strong>with</strong> one view-method coupling.<br />
5.2.3 View Partitioning: OriginatorReceiverView Mail System<br />
In the OriginatorReceiverViewMail class, we re ne the userView of the<br />
UserSystemView Mail System. Therefore we de ne two new views originatorView<br />
<strong>and</strong> receiverView. Note that both these views have smaller result sets<br />
than the original userView. This is an obliged property, because of the <strong>and</strong>composition<br />
of views on the same method(s) through subclasses. The mappings<br />
2. When a runtime message matches a lter element, the message is allowed to continue.<br />
When it has passed all lter elements, <strong>and</strong> thus is still not accepted, the lter acts according<br />
to its type (the error lter will raise an exception, for example)
5.2. <strong>Multiple</strong> <strong>Views</strong> 65<br />
class UserSystemViewMail interface<br />
:::;<br />
internals<br />
mail : Mail; == Subclass from Mail<br />
conditions<br />
userView;<br />
systemView;<br />
input lters<br />
mv1 : Error = f userView ) setMailOriginator,<br />
true ; setMailOriginator g;<br />
:::;<br />
end;<br />
class UserSystemViewMail implementation<br />
conditions<br />
userView<br />
begin<br />
return message.sender.isKindOf:(User)<br />
end;<br />
:::;<br />
end;<br />
Figure 5.2: Implementation of method-view coupling in Sina
66 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
View<br />
ViewA<br />
ViewA<br />
:ViewA<br />
^<br />
^<br />
^<br />
ViewB<br />
:ViewB<br />
ViewB<br />
Method<br />
Method<br />
Method<br />
Method<br />
^OK<br />
p<br />
_OK<br />
p<br />
p<br />
p<br />
:ViewA<br />
ViewA<br />
ViewA<br />
:ViewA<br />
:ViewA<br />
^<br />
^<br />
^<br />
^<br />
^<br />
:ViewB<br />
ViewB<br />
:ViewB<br />
ViewB<br />
:ViewB<br />
Method<br />
:Method<br />
:Method<br />
:Method<br />
:Method<br />
p<br />
p<br />
p<br />
p<br />
p<br />
p<br />
p<br />
p<br />
Table 5.2: Possible mappings between methods <strong>and</strong> multiple views<br />
from the userView to the methods also have to be rede ned to use the new<br />
views.<br />
Again only the Mail class has to be extended. The VPUser subclass<br />
only de nes a test function that uses the OriginatorReceiverViewMail<br />
class. This class shows how view mappings can be composed.<br />
Composing View Mappings<br />
When we want to place one method under more views, we can do this in two<br />
di erent ways:<br />
And-composition This means that the method can only be accepted if both<br />
views are active.<br />
Or-composition This means that the method must be accepted if at least one<br />
view is active.<br />
Which composition is used in a class declaration is totally dependent on the<br />
situation, <strong>and</strong> the developer has to choose the right one. Both versions can<br />
be expressed <strong>with</strong> lters. The <strong>and</strong>-composition is expressed <strong>with</strong> two di erent<br />
lters, <strong>and</strong> the or-composition is expressed <strong>with</strong> one lter. Table 5.2 depicts the<br />
possible situations, <strong>and</strong> whether the situation is OK or not for AND- as well as<br />
OR-composition. See Figure 5.3 for an implementation of both compositions.<br />
Filter mv1 uses AND-composition, while lter mv4 uses OR-composition.<br />
This mechanism has the property that subclassing of a class <strong>with</strong> views<br />
only permits <strong>and</strong>-composition for more views on the same method. This is a<br />
point of discussion in the TRESE group, but intuitively this is OK, because<br />
otherwise you can break integrity rules of superclasses by bypassing existing<br />
view restrictions.<br />
The implementation of class OriginatorReceiverView shows ANDcomposition<br />
through subclassing. Amongst others, the method setMailReceiver<br />
is restricted by both views userView from the parent class <strong>and</strong> the originatorView<br />
from the owner class. Of course this has no e ect, because<br />
V userView<br />
V originatorView
5.2. <strong>Multiple</strong> <strong>Views</strong> 67<br />
class OriginatorReceiverViewMail interface<br />
:::;<br />
internals<br />
mail : UserSystemViewMail; == Inherit<br />
conditions<br />
originatorView;<br />
receiverView;<br />
input lters<br />
mv1 : Error = f originatorView ) setMailOriginator,<br />
true ; setMailOriginator g;<br />
:::;<br />
mv4 : Error = f originatorView ) getMailContents,<br />
receiverView ) getMailContents,<br />
true ; getMailContents g;<br />
:::;<br />
end<br />
Figure 5.3: Method View Composition<br />
class GroupMail interface<br />
:::;<br />
conditions<br />
originatorView; == Rede ned view<br />
:::;<br />
end<br />
Figure 5.4: View Extension only rede nes the view<br />
But this does depend completely on the de nitions of the views that are involved.<br />
The implementation also shows OR-composition. The method getMail-<br />
Contents can be called by both the mailOriginator <strong>and</strong> the mailReceiver ( lter<br />
mv4 in Figure 5.3).<br />
5.2.4 View Extension: Group Mail System<br />
In the GroupMail class we extend the de nition of the originatorView. We<br />
check if the \real" originator <strong>and</strong> the sender of the message belong to the same<br />
group. Note that only the view de nition has changed, directly re ecting the<br />
change of the speci cation (Figure 5.4).<br />
To be able to test group membership of a User, we extend the de nition<br />
of the User class. A GroupUser has a groupNumber attribute, so we can<br />
check if groupNumbers of two di erent users match.
68 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
class SecureMail interface<br />
:::;<br />
conditions<br />
pgpView;<br />
input lters<br />
dis : Dispatch =f<br />
pgpView->[getMailContents]getPGPMailContents,<br />
pgpView->[setMailContents]setPGPMailContents,<br />
inner. , mail. g;<br />
end<br />
Figure 5.5: Conditionally redirect messages to specialized versions<br />
5.2.5 Dynamic Behaviour Extension: Secure Mail System<br />
For the Secure Mail System, we de ne a new view pgpView on the SecureMail<br />
class. This view is active when the sender of the message supports the PGP protocol.<br />
When the PGP protocol is supported, the new get- <strong>and</strong> setMailContents<br />
methods that support PGP encoding <strong>and</strong> decoding are used. Otherwise the<br />
\normal" methods are used.<br />
Therefore we only have to declare the view pgpView, <strong>and</strong> lter expressions<br />
that modify the get- <strong>and</strong> the setMailContents to their PGP-aware counterparts.<br />
Figure 5.5 shows how the lter expression redirects the incoming messages,<br />
depending on the view.<br />
The User class has to be extended <strong>with</strong> PGP semantics, otherwise the<br />
SecureMail class is not able to determine if the User supports the protocol,<br />
<strong>and</strong> to get en- <strong>and</strong> decoding keys from the User for coding of the mailContents.<br />
5.2.6 Static Meta Behaviour Extension: Warning2 Mail System<br />
In the Warning2Mail class, we introduce nothing else but a counter object<br />
that counts the incoming messages. When a message was sent before, a warning<br />
is issued. Otherwise the message is counted, <strong>and</strong> execution continues normally.<br />
The counting is done in a separate object MCount. Note that this object<br />
does not know the structure of the Warning2Mail class, or even what methods<br />
it should count. The object structure <strong>and</strong> the counting (<strong>and</strong> warning) behaviour<br />
are neatly separated in the classes Warning2Mail <strong>and</strong> MCount. See<br />
Figure 5.6 how the counting property is added to the appropriate methods.<br />
The Warning2User class only implements a new test routine.<br />
5.2.7 View Composition: Protected Mail System<br />
For the protected mail system, we rst introduce the class SecureDocument.<br />
This class de nes a securityLevel, <strong>and</strong> a view which checks whether the sending<br />
user has security clearance. This means that the securityLevel of the sending<br />
user has to match at least the securityLevel of the SecureDocument.
5.3. <strong>Layering</strong> 69<br />
class Warning2Mail interface<br />
internals<br />
mail : SecureMail; == Inherit<br />
messageCounter : MCount; == Counter<br />
input lters<br />
count : Meta = f [setMailContents,setMailOriginator,<br />
setMailReceiver,send]<br />
messageCounter.warning2Message g;<br />
dis : Dispatch =f inner. , mail. g;<br />
end<br />
Figure 5.6: Coupling meta behaviour to an object<br />
class ProtectedMail interface<br />
internals<br />
mail : Warning2Mail; == Inherit<br />
secdoc : SecureDocument; == Inherit<br />
input lters<br />
err : Error = f securityClearance -><br />
fgetMailContents, setMailContentsg,<br />
true ;fgetMailContents, setMailContentsg g;<br />
dis : Dispatch =f inner. , mail. , secdoc. g;<br />
end<br />
Figure 5.7: Composing views is extremely simple using Composition Filters<br />
For this example, we also need to de ne a SecureUser, which implements<br />
the securityLevel attribute. This SecureUser also implements a new<br />
test method.<br />
The SecureMail class, which is the composition of Mail <strong>and</strong> Secure-<br />
Document, is extremely simple. As we can see in Figure 5.7, we only declare<br />
the inheritance of the proper classes, <strong>and</strong> de ne the necessary method-view<br />
mappings for the securityClearance of the Get/Set contents methods.<br />
5.3 <strong>Layering</strong><br />
In this section, we will give the Sina solution for the implementation of di erent<br />
perceptions of layering, as discussed in Chapter 4.<br />
Just as <strong>with</strong> the C ++ solution, the Sina implementation also is based on<br />
the Simple Mail System, so we will start from there.
70 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
5.3.1 Add Methods: Heading Mail System<br />
In the User class, we constructed a header for textual representation of the<br />
MailMessage by h<strong>and</strong>. In the HeadingMail, we provide a function that constructs<br />
the header for us. MailMessages <strong>with</strong> more enhancements then can include<br />
these enhancements in the header automatically.<br />
We de ne the new functionality in the HeadingMail class by de ning<br />
the getMailHeading method. We use this method in the getMailAsText method.<br />
To use the new functionality, we de ne a HUser class, which uses this new<br />
header. This class also de nes a new test function.<br />
Note that all \self" references are denoted as server calls. This is because<br />
Sina is a delegation-based language, where this refers to the implementor of the<br />
current method, instead of the original receiver.<br />
5.3.2 Rede ne Methods: Attachment Mail System<br />
In the AttachmentMail, we will enable the user to attach a document tothe<br />
MailMessage. For this, we de ne (like in the C ++ implementation) a separate<br />
Attachment class, which we will use in the class AttachmentMail.<br />
The AUser class only de nes a new test method.<br />
When an attachment is added to the MailMessage, we want that the<br />
mail header updates accordingly. For this, we only have to rede ne the getMail-<br />
Heading method.<br />
There is one signi cant di erence <strong>with</strong> the C ++ implementation. In C ++,<br />
there was a conditional statement (if. . . then. . . else), to decide whether or<br />
not the attachment information was to be added to the mail header. There are<br />
three issues involved here:<br />
1. The method;<br />
2. The object state<br />
3. How these are related to each other.<br />
These issues correspond to the method getMailHeading, the condition<br />
noAttachment <strong>and</strong> the skipMe lter of Figure 5.8. The lter section exactly<br />
states that normally the inner methods are preferable (as in normal inheritance),<br />
but that this must be skipped as long there is no Attachment present.<br />
Note that these issues are the same as in Section 3.1.2. In that section is<br />
explained why separation of these issues is so important.<br />
5.3.3 Extend Methods: ReadNoti cation Mail System<br />
The functionality that we will add in the ReadNotificationMail class is<br />
orthogonal to the \normal" object behaviour, as we have already stated in<br />
Section 4.2.3. Therefore, we de ne the semantics for the noti cation mechanism<br />
in a separate class Notifier.<br />
The new mail class ReadNotificationMail itself is very simple now.<br />
Because we isolated the noti cation semantics, the new ReadNotification-<br />
Mail class only has to attach these semantics to the Mail class, which is done
5.3. <strong>Layering</strong> 71<br />
class AttachmentMail interface<br />
internals<br />
mail : HeadingMail;<br />
conditions<br />
noAttachment;<br />
methods<br />
:::;<br />
getMailHeading;<br />
input nters<br />
skipMe : Dispatch =f<br />
noAttachment)[getMailHeading]mail.getMailHeading; g<br />
disp : Dispatch =f inner. , mail. g<br />
end<br />
Figure 5.8: Code example of conditional method skipping<br />
class HistoryMail interface<br />
internals<br />
mail : ReadNoti cationMail;<br />
history : HistoryReporter;<br />
input lters<br />
meta : Meta = f [ ]history.saveHistory g;<br />
disp : Dispatch =f history.historyReport, mail. g;<br />
end<br />
Figure 5.9: Orthogonal behaviour is very simple to add to an existing class<br />
in the meta lter. It focuses on when to alarm the noti er, <strong>with</strong> respect to the<br />
Mail object itself. It is up to the Noti er to provide means for enabling <strong>and</strong><br />
disabling noti cation, <strong>and</strong> to prevent double noti cation sends.<br />
5.3.4 Add Object-Orthogonal Behaviour: History Mail System<br />
Like in the ReadNoti cation Mail System, the History Mail System de nes<br />
a class which de nes behaviour orthogonal to that of the normal object. The<br />
HistoryMail class records all incoming messages <strong>and</strong> provides a way to display<br />
these recordings.<br />
While the impact of the implementation of this semantics in C ++ was<br />
very big (all existing methods had to be rede ned), the Sina implementation<br />
is simple <strong>and</strong> straightforward. It resembles the ReadNotificationMail implementation,<br />
because they both implement orthogonal behaviour. The class<br />
interface is shown in Figure 5.9.
72 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
incoming message<br />
4<br />
1<br />
new meta...<br />
new object...<br />
2<br />
dynamicLayer<br />
basicObject<br />
5<br />
metaLayer<br />
6<br />
objectLayer<br />
Figure 5.10: Structure of an object <strong>with</strong> dynamic layering property<br />
5.3.5 Dynamic <strong>Layering</strong>: Dynamic Mail System<br />
All functionalities have been implemented statically so far, which means that<br />
their functionalities are always present, whether they are used or not. We have<br />
seen that implementing dynamic layering in C ++ is rather di cult, introducing<br />
more problems than bene ts. In this section we show how dynamic layering can<br />
be implemented using the Composition Filters approach.<br />
The idea is as follows: we start <strong>with</strong> a default object implementation, <strong>and</strong> adapt<br />
it to enable dynamic layering on the object. This way, we will be able to get the<br />
run-time situation of Figure 4.7. We do this by de ning the structure depicted<br />
in Figure 5.10. In this gure, all incoming messages will be routed through all<br />
present meta-level layers, <strong>and</strong> after that through all object-level layers. After<br />
that, the message will be directed to the object itself as usual. New layers will be<br />
tted in front of the appropriate layer-chain. This way, newly added layers can<br />
use <strong>and</strong>/or override present functionality, like in normal inheritance situations.<br />
The basics are de ned in class BasicDL, which implements the dynamic<br />
layering principles for both the layered object as well as the layers. 3<br />
In Figure 5.11, we can see that the HistoryProperty combines the<br />
dynamic layering feature from BasicDL <strong>and</strong> the history recording from our<br />
earlier de ned HistoryReporter just by declaring them as appropriate.<br />
5.4 Conclusions<br />
Apart from some minor problems, we can conclude that views as well as object<br />
layers can very easily be expressed <strong>with</strong> Composition Filters. We have seen<br />
that we did not have to make adaptions to the Mail class when we introduced<br />
3. See Appendix D.5, where both HistoryProperty <strong>and</strong> DynamicMail \inherit" from<br />
basicDL<br />
3
5.4. Conclusions 73<br />
class HistoryProperty interface<br />
internals<br />
basics : BasicDL;<br />
oldReporter : HistoryReporter;<br />
methods<br />
process(aMessage : SinaMessage) returns nil;<br />
input lters<br />
disp : Dispatch =f<br />
inner. ,<br />
oldReporter.historyReport,<br />
basics. g;<br />
end<br />
Figure 5.11: Composing functionalities goes rather well using Composition Filters<br />
views. We only de ned the needed views, <strong>and</strong> coupled them to the appropriate<br />
methods <strong>with</strong> lter expressions. Also the changes we made to the Mail classes<br />
following the scenario tted directly into our model.<br />
We are not the rst who address views in object oriented software models. Some<br />
other people also have tried to make models that explicitly modelled the views.<br />
Surrogates<br />
Minsky <strong>and</strong> Pal (1995) address a technique called \surrogates" for implementing<br />
di erent views over objects. For every view, a special surrogate object is created,<br />
which enables or disables speci c features of the original object by the use of<br />
so-called surrogate rules. With this mechanism it is possible to de ne simple<br />
access control over classes or even individual objects, but our model goes much<br />
further.<br />
Surrogates cannot provide access dependent on the actual state of the object,<br />
the message or its context. Therefore the classes GroupMail, SecureMail,<br />
Warning2Mail <strong>and</strong> ProtectedMail cannot be realised<br />
<strong>with</strong> surrogates.<br />
It is not possible to de ne views that are composed from other views,<br />
or provide access based on more views than just one. If we had sent a<br />
MailMessage from some User to herself, this User would be the Mail-<br />
Originator as well as the MailReceiver. This cannot be expressed neatly<br />
<strong>with</strong> surrogates, because this person then has to have two references to<br />
the same MailMessage.<br />
Clients of surrogates are aware of the existence of the views, <strong>and</strong> must<br />
reference them by name. As a result, the OriginatorReceiverView<br />
example is possible, but it would have triggered a rewrite of the rest of<br />
the code at all places to reference the correct Mail surrogate.
74 Chapter 5. Composition Filters Solutions for the Modelling Issues<br />
Layers normally are referred to as layers from the OSI reference model (Black<br />
1991), where one layer is implemented in terms of another layer.<br />
We have shown layers in another perspective, <strong>and</strong> also have shown that<br />
implementing these in a traditional language is not that simple. Implementing<br />
layers in a language like Sina is straightforward however. Even dynamic layering<br />
is possible, opening a new world of modelling possibilities for us.
Chapter 6<br />
<strong>Composable</strong> Models Presented as Design Patterns<br />
Chapter 5 presents adequate solutions for implementing <strong>Multiple</strong> <strong>Views</strong> on,<br />
<strong>and</strong> <strong>Layering</strong> of objects. However, the solutions are not presented in a way<br />
suitable for knowledge distribution. In this chapter, we will provide the models<br />
for <strong>Multiple</strong> <strong>Views</strong> <strong>and</strong> Dynamic <strong>Layering</strong> in a more accessible format, using<br />
Design Pattern presentation style.<br />
In Section 2.2, we introduced Design Patterns as a knowledge presentation<br />
<strong>and</strong> distribution medium. Section 6.1 will evaluate pattern denotations<br />
in more detail, <strong>and</strong> presents an adapted denotation for Design Patterns, which<br />
is capable of presenting composable models for design problems. Sections 6.2<br />
<strong>and</strong> 6.3 then present the modelling issues as design patterns.<br />
6.1 Enabling Design Patterns to Present <strong>Composable</strong> Models<br />
The notations in which patterns appear nowadays are not adequate for the<br />
problems we have solved. The reason for this is the rich semantics of Composition<br />
Filters, which is not present in \st<strong>and</strong>ard" models, <strong>and</strong> thus is not covered<br />
by the well-known pattern denotations.<br />
The Composition Filters Object Model is capable of adapting message<br />
passing semantics in a very exible way. It is possible to \inspect" several<br />
attributes of a message at runtime because these attributes, like the sender of<br />
the message, are made explicit in the model. It is also possible to change these<br />
message attributes, or let the object react in a speci c way to the message by<br />
choosing the appropriate lter type. It is even possible to reify the message as<br />
a rst class object, <strong>and</strong> pass it to another object for further processing, in fact<br />
enabling us to implement new lter types on the y.<br />
When we want to express Composition Filters Object Model solutions in<br />
a pattern format, we must be able to express all these semantics in a suitable<br />
way. It is possible to give Sina code listings for solutions. This would not be<br />
adequate however, because we then bind the solution to a speci c language. A<br />
Design Pattern should present a solution that is more or less language independent.<br />
75
76 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
The patterns de ned by Gamma et al. (1995) are clearly focusing on<br />
the traditional object model as discussed in 2.1.1. Instead, we want topresent<br />
modelling problems using the Composition Filters Object Model. The graphical<br />
models identi ed <strong>and</strong> used by Gamma et al. (1995) are not rich enough for this.<br />
They use the following three graphical notations:<br />
1. Class Diagrams. These are used to model class structures, which depict<br />
static structural relations.<br />
2. Object Diagrams. These are used to model object structures, which depict<br />
dynamic structural relations.<br />
3. Interaction Diagrams. These are used to model object interactions <strong>and</strong><br />
the order in which they occur.<br />
We will now add a graphical notation to the vocabularies of a Design Pattern,<br />
called a Message Diagram.<br />
Message Diagrams<br />
The model that we provide is focusing almost completely on the messages that<br />
are sent between objects. It is however not important in what order messages<br />
are sent, like in interaction diagrams. It is important what happens when a<br />
message is sent to an object. The focus lies on one (or a group) of messages as<br />
one entity, <strong>and</strong> not on the relation between these messages, like their execution<br />
order.<br />
We will introduce a model that we need for expressing our solutions.<br />
The diagram we need is called a Message Diagram. Its elements match, not<br />
surprisingly, the Composition Filters Object Model elements.<br />
Initial graphical notation<br />
In Figure 6.1, we see both a normal <strong>and</strong> a ltered message being sent from the<br />
sending object to the receiving object. The normal message is supposed to look<br />
familiar. With the ltered message, we see that the message's lifetime is divided<br />
by (one or more) lter(s) into a pre- ltered, a being- ltered <strong>and</strong> a post- ltered<br />
part. With an input lter, this lter is an integral part of the receiving object.<br />
In this case, the nal target of the message is the part of the receiving object<br />
that comes after the lter, <strong>and</strong> is called the server of the message in Sina.<br />
Elements of a Filter Speci cation<br />
We can identify three di erent elements of a lter speci cation: a condition,<br />
a matching <strong>and</strong> a substitution part. The condition is optional, <strong>and</strong> defaults to<br />
True. The substitution part is also optional, <strong>and</strong> defaults to the matching part,<br />
which isnot optional.<br />
A message is said to be accepted by a lter, if the condition evaluates to<br />
True, <strong>and</strong> if the message selector equals the matching part of the lter speci -<br />
cation. If a substitution part is speci ed, the message selector <strong>and</strong>/or it's target<br />
are replaced <strong>with</strong> the speci ed values.
6.1. Enabling Design Patterns to Present <strong>Composable</strong> Models 77<br />
anObject<br />
aMessage<br />
(a) Normal message<br />
aTarget<br />
filter<br />
anObject<br />
prefiltered postfiltered<br />
aTarget<br />
aMessage<br />
(b) Filtered message<br />
Figure 6.1: Graphical message notations from the message's viewpoint. A message<br />
is either not ltered at all, or passes one or more lters which inspect<br />
<strong>and</strong>/or manipulate its runtime behaviour.<br />
We can express this by labelling the pre- ltered message <strong>with</strong> the matching<br />
part (which can be a wildcard), <strong>and</strong> the post- ltered message <strong>with</strong> the<br />
condition <strong>and</strong>, if present, the substitution part.<br />
If the message is not accepted by the lter, it is said to be rejected. It<br />
depends on the lter type what will happen in that case. It depends on the<br />
situation whether it is illustrative to explicitly denote this case or not.<br />
Semantics of a Filter<br />
So far, the lter only accepts or rejects messages. The lter type dictates what<br />
happens when a message is accepted or rejected by this lter. Until now, six<br />
lter types have been de ned:<br />
1. Error lter. An error is raised when no matching succeeds.<br />
2. Wait lter. Execution will be deferred until the message falls through the<br />
lter.<br />
3. Meta lter. Execution will proceed at a meta-level after the message has<br />
been rei ed into a rst-class object. There the message can be inspected<br />
<strong>and</strong> even manipulated. After meta-processing, the message will continue<br />
executing back at the object-level.<br />
4. Dispatch lter. Execution is either dispatched to the implementation<br />
which is present in the inner object, or to the rst lter of the object to<br />
which the message is delegated.<br />
5. Send lter. Execution is transferred to the object to which the message<br />
is sent (to its set of input lters).<br />
6. Realtime lter. Execution is assigned realtime constraints such as maximum<br />
execution time.
78 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
Wait Error Meta Dispatch Send RealTime<br />
Figure 6.2: Filter Types<br />
We visualise these types by using speci c drawings for the di erent lter<br />
types, as depicted in Figure 6.2. Note that both the Dispatch <strong>and</strong> the Send lter<br />
are very simple. They are the placeholders for the dispatch <strong>and</strong> send mechanisms<br />
of the traditional object model (<strong>with</strong> the additional features of the Composition<br />
Filters Object Model of course). Often it is not necessary to depict these lters<br />
explicitly, sowe omit them in our Message Diagrams to keep them as simple as<br />
possible.<br />
Message States<br />
When a message is sent from aClient to aServer, it passes several stages. We<br />
already mentioned that a lter in most cases is some kind of wrapper around the<br />
original (core) object. The message then can be between two di erent objects,<br />
or between the core object <strong>and</strong> the lters (i.e. it has passed the lters). To<br />
make this di erence visible, we denote the message <strong>with</strong> a normal line when<br />
it resides between the objects, <strong>and</strong> <strong>with</strong> a thicker line when it is between the<br />
lters <strong>and</strong> the receiving object. When the diagram depicts an output lter, the<br />
line between the sending object <strong>and</strong> the lter will be the thicker line, because in<br />
such a diagram, the sending object is the core object the diagram is all about.<br />
Normal, unimportant <strong>and</strong> Core <strong>Objects</strong><br />
<strong>Objects</strong> or classes of objects can play di erent roles in a message diagram. To<br />
make this clear, we use di erent displaycharacteristics for di erent object roles.<br />
We identify three kinds of object roles:<br />
Unimportant object An object is called unimportant, if it is present in the<br />
object interaction, but is irrelevant to the communication characteristics.<br />
It is used mostly to identify the context of a communication channel. We<br />
will display an unimportant object grayed. Gamma et al. (1995) uses the<br />
same denotation.<br />
Normal object A normal object is an environmental object which plays a key<br />
role in the communication characteristics. We display normal objects in<br />
black.<br />
Core object The core object is the target of the message. It is displayed in<br />
thick black.<br />
Filter interdependencies<br />
Usually, an object has more than one lter element de ned, in one or more<br />
lters. When the evaluation order of lter elements is important, we must show
6.1. Enabling Design Patterns to Present <strong>Composable</strong> Models 79<br />
this in our message diagrams. When more than one communication line comes<br />
out of a lter, they must be read top-down. The implementation of the dynamic<br />
mail system from Chapter 4 gives a nice example of this situation. Figure 6.10<br />
on page 87 shows (a part of) the message diagram.
80 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
aMailH<strong>and</strong>ler<br />
getContents getMailReceiver<br />
aUser<br />
getContents<br />
sendMail<br />
getMailReceiver<br />
aMail<br />
Figure 6.3: An example mail system<br />
6.2 Design Pattern: <strong>Composable</strong> <strong>Multiple</strong> Object <strong>Views</strong><br />
Intent<br />
The pattern makes it possible to explicitly model dynamic interface <strong>and</strong> behaviour<br />
change, dependent onthe runtime message context, like the sender of<br />
a message.<br />
Also Known As<br />
<strong>Multiple</strong> Interfaces<br />
When we want to model di erent behaviour or interfaces dependent on the state<br />
of the object itself instead of the sender of a message.<br />
State<br />
The State pattern provides an alternative solution for more or less the same<br />
problem. Further discussion in the Related Patterns section.<br />
Motivation<br />
Consider a mailing system. This system has the participants Mail, User <strong>and</strong><br />
MailH<strong>and</strong>ler (see Figure 6.3). When we look at the interface of Mail, we<br />
see two parts there. These are<br />
User part This part provides the interface to the User objects. Typical examples<br />
are getContents <strong>and</strong> sendMail.<br />
System part This part provides the interface to the MailH<strong>and</strong>ler.Atypical<br />
example is getMailReceiver.<br />
These two parts provide di erent functionalities of the Mail object, which are<br />
more or less independent of each other.<br />
In the implementation of this system, we want to prevent that the Mail objects<br />
receive inappropriate messages from other objects. We want to prevent for<br />
example that Mail receives the getContents method from the MailH<strong>and</strong>ler,<br />
because it violates the rules of the system as a whole. This is seen in Figure 6.3,
6.2. Design Pattern: <strong>Composable</strong> <strong>Multiple</strong> Object <strong>Views</strong> 81<br />
aClient<br />
*<br />
anotherMessage<br />
aView -> aMessage<br />
aServer<br />
Figure 6.4: The structure of the <strong>Multiple</strong> <strong>Views</strong> pattern<br />
where the message getContents is blocked when it is sent by the MailH<strong>and</strong>ler,<br />
while it is passed through when it is sent byaUser.<br />
Further, we want to explicitly divide the interface in multiple sections,<br />
more or less explaining the di erent roles Mail can play in di erent activities.<br />
This way the implementation of Mail will be better understood.<br />
In intuitive implementations of the above requirements, the accessibility code<br />
will be mixed <strong>with</strong> the application code. For example, in the implementation of<br />
getContents, we will check whether the sender of the message is a User object.<br />
The disadvantage is twofold:<br />
1. Adapting access restrictions in subclasses will result in rewriting all restricting<br />
application methods.<br />
2. Adapting application semantics will force you to rewrite all access restriction<br />
code.<br />
The above problem arises from the fact that access control <strong>and</strong> application<br />
semantics are orthogonal properties, which are combined as application<br />
semantics in the implementation. Our solution will prevent this undesired situation.<br />
Applicability<br />
Apply <strong>Composable</strong> <strong>Multiple</strong> Object <strong>Views</strong> when:<br />
The interface of a class is complex <strong>and</strong> consists of several `sub-interfaces',<br />
each for a di erent system functionality.<br />
Object misuse must be prevented, <strong>and</strong> several parts of the interface<br />
should be protected from some clients (message callers).<br />
Application semantics or object access control must be adapted through<br />
subclassing.<br />
Implementation of methods must be adapted dynamically (depending on<br />
message sender or internal object state).<br />
Structure<br />
The structure of the pattern is as depicted in Figure 6.4. Here we showaClient<br />
object, which sends aMessage to the Server, which is accepted under condition<br />
aView. This picture also shows the message anotherMessage, which is blocked<br />
by the server.
82 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
Participants<br />
Server<br />
The Server is responsible for implementing aView, aMessage <strong>and</strong> the dependency<br />
between these two.<br />
Collaborations<br />
The Server receives aMessage, inspects whether aView is active, <strong>and</strong><br />
then processes or rejects the message.<br />
Consequences<br />
Using this pattern has the following bene ts:<br />
Separation of concerns The model consists of two di erent elements (application<br />
<strong>and</strong> view). We separate these concerns explicitly.<br />
Polymorphic The solution is polymorphic; i.e. it is possible to implement only<br />
di erent application or view semantics in subclasses.<br />
Using this pattern has the following drawback:<br />
Encapsulation The Composition Filters Object Model de nes lters always<br />
at the interface level. In this example this is all-right, because we want to<br />
inform the user (client) about the views <strong>and</strong> their restrictions. When we<br />
want to adapt behaviour under certain circumstances (see the Gamma<br />
State pattern), we do not want to show this at the interface of the<br />
object. This is not possible <strong>with</strong> the Composition Filters Object Model.<br />
Implementation<br />
The Server class has three concepts: the method, the view <strong>and</strong> the connection<br />
between these two elements. This results in the solution template in Figure 6.5<br />
for the <strong>Composable</strong> <strong>Multiple</strong> Object <strong>Views</strong> pattern.<br />
This template shows a view aView. This aView restricts access to aMessage,<br />
while access to method yetAnotherMessage is not restricted. Here can also<br />
be seen that addition of more views is possible, by de ning an additional view<br />
in a subclass, <strong>and</strong> connecting it to methods using an additional lter expression.<br />
Sample Code<br />
The solution we propose uses the concepts that are built-in in the Composition<br />
Filters Object Model. The view userView is represented by a condition. The<br />
connection between the view <strong>and</strong> the application semantics is represented by a<br />
message lter. This results in the class de nition shown in Figure 6.6. An extract<br />
from the implementation, in order to show how the userView is implemented<br />
using Composition Filters Object Model primitives, is shown in Figure 6.7.<br />
Known Uses<br />
None.
6.2. Design Pattern: <strong>Composable</strong> <strong>Multiple</strong> Object <strong>Views</strong> 83<br />
class Server interface<br />
conditions<br />
aView;<br />
methods<br />
aMessage;<br />
yetAnotherMessage;<br />
inputFilters<br />
mv: Error = faView ) aMessage, true ; aMessageg;<br />
dis: Dispatch =finner. g;<br />
end<br />
Figure 6.5: Code template for the <strong>Multiple</strong> <strong>Views</strong> Pattern<br />
class Mail interface<br />
comment<br />
This class implements the <strong>Multiple</strong> <strong>Views</strong> design pattern<br />
internals<br />
contents: Text; == Contains the mail message<br />
conditions<br />
userView; == Implements the view<br />
methods<br />
== Implements the application functionality<br />
getContents returns Text;<br />
inputFilters<br />
== Connect the view <strong>with</strong> the application semantics<br />
mv: Error = fuserView ) getContents, true ; getContentsg;<br />
dis: Dispatch =finner. g;<br />
end<br />
Figure 6.6: Interface de nition of the Mail class
84 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
class Mail implementation<br />
:::<br />
conditions<br />
userView<br />
begin<br />
return sender.isKindOf(User)<br />
end<br />
:::<br />
end<br />
Related Patterns<br />
Figure 6.7: Implementation extract of the Mail class<br />
State Partitioning This problem is also known as the View Partitioning<br />
Problem. It's basis lies in the fact that it is normally not possible to<br />
divide a view in two distinct subviews, <strong>with</strong>out breaking the inheritance<br />
principle <strong>and</strong> rewriting parts of the class speci cation.<br />
State The Gamma catalogue provides the State pattern for implementing dynamically<br />
changeable behaviour. This pattern has a big disadvantage:<br />
the pattern is not extensible, <strong>and</strong> thus implementations of the pattern<br />
are not reusable.<br />
This statement is based on the fact that the State hierarchy <strong>and</strong> the<br />
Context are not orthogonal (same problem as stated before). This<br />
means that extending the Context is not possible <strong>with</strong>out rewriting at<br />
least a part of the State hierarchy. Furthermore, when a subset of the<br />
Context implementation is valid for more that one particular State,<br />
this results in replication of implementation code. This, of course, is undesirable,<br />
<strong>and</strong> undoes a part of the positive e ects of using the State<br />
pattern.
6.3. Design Pattern: <strong>Composable</strong> Object <strong>Layering</strong> 85<br />
getContents<br />
aMailH<strong>and</strong>ler<br />
getMailReceiver<br />
aUser<br />
getContents<br />
sendMail<br />
aHistory-<br />
Recorder<br />
recordHistory<br />
aMail<br />
Figure 6.8: An example mail system <strong>with</strong> history recording<br />
6.3 Design Pattern: <strong>Composable</strong> Object <strong>Layering</strong><br />
Intent<br />
Attach additional behaviour to an object dynamically. <strong>Composable</strong> Dynamic<br />
Object Layers pattern is used to compose an object's behaviour <strong>with</strong> highly<br />
reusable components, <strong>with</strong>out losing the features of object oriented modelling.<br />
Also Known As<br />
None.<br />
Motivation<br />
In sophisticated software frameworks, some important objects incorporate many<br />
di erent features. These features however are almost never used together. Normally,<br />
only some of these features are used in speci c situations. The di erent<br />
features then can be turned on or o using some calls (like enableFeatureThisOrThat).<br />
The implementation of these objects often becomes heavy loaded <strong>with</strong><br />
administrative code for enabling <strong>and</strong> disabling of features, <strong>and</strong> checking if features<br />
are enabled. Also, the di erent code sections of di erent features are often<br />
mixed together. This leads to complex, badly readable <strong>and</strong> non reusable code.<br />
It is also not possible to tailor the di erent features <strong>with</strong>out rewriting other<br />
code parts.<br />
Consider a Mail System, like in Figure 6.8. It resembles the mail system of<br />
Figure 6.3, <strong>with</strong> the di erence that all incoming messages are recorded in a<br />
HistoryRecorder. Often this functionality is not required, so it should be possible<br />
to enable <strong>and</strong> disable the history recording service. The disadvantage of this<br />
static structure is twofold:<br />
1. All Mail objects not requiring the history recording service are loaded<br />
<strong>with</strong> its (disabled) code, which results in unnecessary resource occupation.<br />
2. It is not possible to tailor the history recorder, because it is encapsulated<br />
in the Mail class.
86 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
getContents<br />
aMailH<strong>and</strong>ler<br />
getMailReceiver<br />
aUser<br />
getContents<br />
sendMail<br />
process<br />
aMessage-<br />
Decoder<br />
aHistory-<br />
Recorder<br />
aMail<br />
process<br />
Figure 6.9: Mail system <strong>with</strong> a history recorder <strong>and</strong> a message decoder<br />
3. When other services are designed, the Mail class has to be extended<br />
to use this service. When lots of these services are involved, this implies<br />
heavy impact on the implementation of the Mail class, while the intrinsic<br />
implementation of the class does not change at all.<br />
Using the <strong>Composable</strong> Dynamic Object Layers pattern, we get a more<br />
exible implementation. See for example Figure 6.9, where besides the HistoryRecorder<br />
also a MessageDecoder is active. Both services are activated transparently,<br />
when a message is sent totheMail object.<br />
Applicability<br />
Apply the <strong>Composable</strong> Dynamic Object Layers when:<br />
Class de nitions consist of many di erent services, which almost never<br />
are used all at the same time.<br />
It must be possible to dynamically add services to an object.<br />
It can not be foreseen which services are necessary in an object. This is<br />
only the case <strong>with</strong> so-called orthogonal services (like the HistoryReporter<br />
mentioned before).<br />
Many of the de ned services can be combined. When inheritance is used<br />
in this situation, many class de nitions are the result, because all di erent<br />
combinations must be de ned explicitly.<br />
Structure<br />
We divide the structure of the <strong>Composable</strong> Dynamic Object Layers pattern<br />
in two parts. The rst part is the Basic Dynamic Layer, which is depicted in<br />
Figure 6.10. The second part is the usage of this Basic Dynamic layer in an<br />
object that needs dynamic layering. It is shown in Figure 6.11<br />
Participants<br />
BasicDL The Basic Dynamic Layer implements the protocols for the layered<br />
object <strong>and</strong> both the object-level <strong>and</strong> the meta-level layers.
6.3. Design Pattern: <strong>Composable</strong> Object <strong>Layering</strong> 87<br />
×<br />
addOL<br />
aClient aBasicDL<br />
addML<br />
(cascaded)<br />
(meta)<br />
process<br />
object_layer<br />
meta_layer<br />
Figure 6.10: Message Diagram of the Basic Dynamic Layer<br />
anObject<br />
*<br />
process<br />
*<br />
*<br />
aBasicDL<br />
aDLObject<br />
Figure 6.11: Message Diagram of the <strong>Composable</strong> Object Layer Pattern
88 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
ObjectLayer De nes the BasicDL protocol by inheriting from it, <strong>and</strong> additional<br />
functionality that must be added to the DLObject object at the<br />
object level.<br />
MetaLayer De nes the BasicDL protocol by inheriting from it, <strong>and</strong> additional<br />
functionality that must be added to the DLObject object at the<br />
meta level.<br />
DLObject De nes the BasicDL protocol by inheriting from it, <strong>and</strong> the normal<br />
functionality that the object must provide.<br />
Collaborations<br />
The BasicDL de nes a protocol for adding new layers to the DLObject<br />
to which it is attached. The newly added layers are chained in such a<br />
way, that newly added layers are processed rst. In this way, newly added<br />
layers can use functionality present in an earlier added layer.<br />
The BasicDL object also delegates all unknown methods to its internal<br />
object-level <strong>and</strong> meta-level layer chains.<br />
The ObjectLevel processes requests which it implements, <strong>and</strong> delegates<br />
all other requests to its BasicDL ancestor.<br />
The MetaLevel implements the process method, <strong>and</strong> forwards the call<br />
to its BasicDL ancestor afterwards. It can also implement object-level<br />
functionality in appropriate methods. All unknown messages should be<br />
delegated to its BasicDL ancestor.<br />
The DLObject object sends all incoming messages to the meta-level process<br />
method. After that, appropriate messages should be delegated to the<br />
BasicDL ancestor. Finally, messages should be dispatched to the inner<br />
object.<br />
Consequences<br />
The <strong>Composable</strong> Dynamic Object Layers pattern has several bene ts:<br />
Flexible property composition All possible combinations of properties can<br />
be constructed at run-time. This avoids class trees which de ne a class for<br />
each possible combination of features. Note that when class de nitions<br />
are used, it is not possible to add features to an object during its lifetime<br />
<strong>with</strong>out losing its object identity.<br />
Avoids feature-loaded classes high up in the hierarchy Because the layers<br />
are attached at run-time, the classes do not have to de ne all features<br />
in advance, resulting in large objects from which only parts will be used.<br />
Layers can be reused It is very simple to reuse layer speci cations in other<br />
classes (especially when they are de ned at the meta-level. The HistoryRecorder<br />
we mentioned before can be plugged into any DLObject<br />
class <strong>with</strong>out modi cations. This way, it is also possible to design a hierarchy<br />
oflayers, separate from the layered objects which will use them.<br />
It will make a design very exible <strong>and</strong> extendible.
6.3. Design Pattern: <strong>Composable</strong> Object <strong>Layering</strong> 89<br />
Implementation<br />
The implementation of the <strong>Composable</strong> Dynamic Object Layers pattern involves<br />
several issues. These include:<br />
The pattern can only be implemented using a language that implements<br />
the Composition Filters Object Model. We have tried to implement it<br />
in a traditional language (C ++, see Appendix C.5), which turned out to<br />
produce more problems than solve them.<br />
The pattern introduces overhead by introducing the BasicDL class.<br />
Don't overuse this pattern, because the implementation overhead we try<br />
to solve <strong>with</strong> this pattern can be less than the overhead the pattern<br />
introduces.<br />
When de ning dynamic layered objects, consider building them on top<br />
of \normal" objects (like the DynamicMail in Appendix D.5). Consider<br />
this also for orthogonal layers (like the HistoryReporter in Appendix<br />
D.5). This way, it is always possible to use the non-dynamic<br />
version when appropriate.<br />
Sample Code<br />
We show the implementation of a dynamic mail object, using a dynamic layer<br />
for history reporting. We assume there is a class Mail which implements normal<br />
mail functionality. Further, there is the BasicDL class which implements<br />
the default dynamic layering protocol. Finally, we assume there is a history<br />
reporting class called HistoryReporter.<br />
First, we show how the HistoryReporter class is made dynamic. The dynamic<br />
version is called HistoryProperty. The code is in Figure 6.12. The<br />
HistoryProperty forwards the process method to the appropriate method in<br />
the HistoryReporter.<br />
The code in Figure 6.13 shows how to make the normal class Mail<br />
dynamic by \inheriting" from BasicDL. Note the di erence <strong>with</strong> Figure 6.12;<br />
the order of the lter elements is di erent. The incoming message is diverted to<br />
the process method rst, for meta-level layering. Then the message is delegated<br />
to the object-level layers, if appropriate. Otherwise, the message is dispatched<br />
to the inner object as usual.<br />
Figure 6.14 shows how to use a dynamic layered object.<br />
Known Uses<br />
None.<br />
Related Patterns<br />
Decorator<br />
The Decorator pattern is the Conventional Object Model counterpart of <strong>Composable</strong><br />
Dynamic Object Layers. It is a di erent pattern, because the structure
90 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
class HistoryProperty interface<br />
internals<br />
basics : BasicDL;<br />
oldReporter : HistoryReporter;<br />
methods<br />
process(aMessage : SinaMessage) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. ,<br />
oldReporter.historyReport,<br />
basics. g;<br />
end;<br />
class HistoryProperty implementation<br />
instvars<br />
methods<br />
process(aMessage : SinaMessage)<br />
begin<br />
oldReporter.saveHistory(aMessage);<br />
basics.process(aMessage);<br />
end;<br />
end;<br />
Figure 6.12: How tomake a generic property a dynamic layer<br />
class DynamicMail interface<br />
internals<br />
layers : BasicDL;<br />
mail : Mail;<br />
input lters<br />
meta : Meta = f [ ]layers.process g;<br />
dis : Dispatch =f layers. , mail. g;<br />
end;<br />
class DynamicMail implementation<br />
end;<br />
Figure 6.13: How tomake a normal class a dynamic layered class
6.3. Design Pattern: <strong>Composable</strong> Object <strong>Layering</strong> 91<br />
main<br />
temps<br />
aMailMessage : DynamicMail;<br />
aHistory : HistoryProperty;<br />
begin<br />
aMailMessage.addML(aHistory);<br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a Dynamic Mail Message');<br />
aMailMessage.send;<br />
aMailMessage.historyReport;<br />
end<br />
Figure 6.14: How to use a dynamic layered object<br />
is very di erent. The goals are the same however. In our solution, we have addressed<br />
some problems that the Decorator pattern introduced. Amongst them<br />
is the problem of losing object identity when a decorator is added to an object.<br />
Dynamic Slots<br />
Schmidt (n.d.) describes an implementation of dynamic slots in the BETA system.<br />
1 Dynamic slots are de ned as dynamically insertable attributes of arbitrary<br />
objects. The di erence between dynamic slots <strong>and</strong> dynamic layering is:<br />
Dynamic slots can only be used to insert attributes, while <strong>with</strong> dynamic<br />
layers, one can insert arbitrary behaviour into any object.<br />
The reference to dynamic slots is not transparant to the user or caller of<br />
the object. One must access these slots in a special way, while dynamic<br />
layers transparantly de ne interface extensions to the object, which can<br />
be accessed as all normal interface elements.<br />
In BETA, dynamic slots are enabled in the root object class, which means<br />
that all objects in the system are dynamic-slot-ready. With dynamic<br />
layering, all objects must explicitly enable this feature before it can be<br />
used. This is the result of enabling the insertion of meta-level layers, <strong>and</strong><br />
the de nition of additional object behaviour on top of already existing<br />
behaviour. If only simple attributes were to be added, 2 one could de ne<br />
one simple superclass which enabled dynamic layering, just as in the<br />
dynamic slot implementation.<br />
1. BETA isawell-known Object-Oriented programming environment.<br />
2. Which is not possible in Sina, but we can de ne simple get <strong>and</strong> put operations which<br />
manipulate some attribute.
92 Chapter 6. <strong>Composable</strong> Models Presented as Design Patterns<br />
6.4 Conclusions<br />
In this chapter we have transformed our design issues from Chapters 3 <strong>and</strong> 4<br />
into Design patterns. We conformed to the format of the GoF book (Gamma<br />
et al. 1995), but we had to make some extension to visualize the semantics of<br />
lters. It is made clear that the GoF format is also suitable for our category of<br />
problem solutions, although we used another object model.<br />
The Message Diagrams we introduced in this chapter are capable of<br />
showing the intensions of some lter set in an intuitive way. In Figure 6.9 for<br />
example, it is immediately clear that users can invoke all Mail methods, that<br />
mail h<strong>and</strong>lers are not supposed to read the mail contents, <strong>and</strong> that all incoming<br />
method calls are processed through a message decoder <strong>and</strong> a history recorder<br />
at a meta level. This overview picture is much harder to underst<strong>and</strong> when read<br />
directly from the lter speci cations.
Chapter 7<br />
Conclusions <strong>and</strong> Future Work<br />
We nalise this thesis by summarising the conclusions. We also give some directions<br />
for further research.<br />
7.1 Comparison of the C++ <strong>and</strong> the Sina implementations<br />
In this thesis we have shown the implementations of two models in two di erent<br />
languages. In this section, we will discuss the results.<br />
7.1.1 <strong>Multiple</strong> <strong>Views</strong><br />
In Table 7.1, we can see the amount ofwork that is necessary to implement the<br />
actions that we have identi ed in the <strong>Multiple</strong> <strong>Views</strong> Model (See Section 3.1.3).<br />
It is obvious that the initial number of methods is the same, because both<br />
implementations must provide the same Mail semantics.<br />
When wewant to add views however, it is clear that an enormous amount<br />
of work has to be done in the C ++ implementation. There are two methods that<br />
implement the views (the same two methods that are necessary for the Sina<br />
implementaton) <strong>and</strong> two times all original interface functions (one time for the<br />
Actions C++ Sina<br />
Initial 14 ? 14 ?<br />
Add <strong>Views</strong> 30 ? 2<br />
View Partitioning 8 ? 2<br />
View Extension 1 1<br />
Dynamic Behaviour Extension 5 ? 1<br />
Static Meta Behaviour Extension 5 ? 0<br />
View Composition 2 ? 0<br />
Table 7.1: Methods added or changed in . . . Mail class to change View aspects.<br />
Numbers marked <strong>with</strong> ? are dependent on the number of a ected methods,<br />
which means that increasing the number of a ected methods will increase the<br />
number in the table.<br />
93
94 Chapter 7. Conclusions <strong>and</strong> Future Work<br />
Actions C++ Sina<br />
Add Methods 2 ? 2 ?<br />
Rede ne Methods 3 ? 4 ?<br />
Extend Methods 5 ? 1<br />
Add Object Orthogonal Behaviour 15 ? 0<br />
Dynamic <strong>Layering</strong> 63 ? 0<br />
Table 7.2: Methods added or changed in . . . Mail class to change Layer aspects<br />
coupling between the view <strong>and</strong> the method, <strong>and</strong> one time for passing the method<br />
to the internal Mail implementation). In Sina, we only provide a simple lter<br />
speci cation.<br />
In all other situations (<strong>with</strong> View Extension as an exception), we have<br />
to do more work in the C ++ implementation than in the Sina implementation.<br />
This is because all a ected methods have to be rewritten in C ++, while in Sina<br />
only lter speci cations have to be adjusted.<br />
7.1.2 <strong>Layering</strong><br />
In Table 7.2, the C ++ implementation is not so bad in the beginning (see Section<br />
4.1.3 for the Layers scenario). When we rede ne methods, the Sina implementation<br />
even has one method more de ned than the C ++ implementation.<br />
This is however because the presence of an attachment is made explicit as a<br />
view in Sina, while in C ++ this is implicitly coded as a NULL check.<br />
When methods are extended, we must de ne ve functions in C ++. These<br />
functions are for the noti cation interface <strong>and</strong> the rede nition of the a ected<br />
Mail functions <strong>and</strong> method-view mappings. In Sina, only the view speci cation<br />
has to be written, accompanied by its method-view mappings.<br />
The addition of meta-functionality is clearly a lot of work in C ++. Adding<br />
othogonal behaviour requires us to rewrite all interface methods, while in Sina<br />
zero functions have to be written. When we de ne dynamically extensible models,<br />
the C ++ implementation follows the Decorator patterns of the Gof book<br />
(Gamma et al. 1995), <strong>and</strong> requires us to write each interface function four(!!)<br />
times: one interface replication for the Mail Component (the Component of the<br />
pattern); one for the DynamicMail interface (the ConcreteComponent of the<br />
pattern); one for the MailDecorator (the Decorator of the pattern); one replication<br />
for the MailHistory (which is a ConcreteDecorator) <strong>and</strong> nally a couple<br />
of methods for the MailReadNoti er (which is also a ConcreteDecorator). As<br />
can be seen, the interface conformance problem that occurs <strong>with</strong> this pattern<br />
is a serious problem. In the Sina implementation this is not a problem at all:<br />
the code of the DynamicMail class contain no methods at all!
7.2. Conclusions 95<br />
7.2 Conclusions<br />
In this thesis we have explicitly focused on the two modelling issues <strong>Multiple</strong><br />
Object <strong>Views</strong> <strong>and</strong> Object <strong>Layering</strong>. Software models often do not explicitly<br />
express views <strong>and</strong> layers, therefore these issues are often bypassed during the<br />
object design.<br />
This leads to software which is hard to reuse <strong>and</strong> maintain, while this<br />
was the reason for using object-oriented modelling techniques in the rst place!<br />
It turns out to be impossible to implement new features <strong>with</strong>out touching or<br />
recoding existing code.<br />
The traditional object-oriented language model lacks some properties,<br />
which are invaluable for expressing modelling issues like those discussed in this<br />
thesis. Amongst them are:<br />
Open message passing semantics.<br />
Meta models for messages.<br />
A delegation mechanism.<br />
We have shown this by implementing a case scenario in C ++, where we<br />
have tried to vary in di erent aspects of the modelling issues.<br />
These properties themselves are not su cient however: Delegation alone<br />
does not solve our problems, because we need to be able to de ne conditions on<br />
the delegation (for <strong>Multiple</strong> <strong>Views</strong> for example). We have tried to implement<br />
our <strong>Multiple</strong> <strong>Views</strong> model in Smalltalk, which is a delegation-based language.<br />
In this implementation we have seen a lot of problems similar to those in C ++<br />
(see Section 3.3 for a more detailed discussion).<br />
It is possible to implement some issue characteristics by replicating interface<br />
speci cations, <strong>and</strong> write \call-through" methods (we have seen that in our C ++<br />
implementations), but this has some drawbacks in general:<br />
Interface conformance. Interfaces needed deeply in a hierarchy must be<br />
declared in upper levels, resulting in a lot of code overhead <strong>and</strong> loss of<br />
overview. See for example our Dynamic <strong>Layering</strong> pattern compared to<br />
the Decorater pattern of Gamma et al. (1995).<br />
Call-throughs are not optimizable. With Composition Filter speci cations,<br />
we write interface declarations. These declarations eventually can<br />
be optimized into executable code by the compilers. When we write callthroughs,<br />
we write interface implementations, which will be executed in<br />
the way we have de ned them, <strong>and</strong> thus they are not optimized. This<br />
will lead to slower execution.<br />
We also have shown that the Composition Filters Object Model is capable of<br />
expressing the modelling issues in a natural way, while the normal properties of<br />
object-oriented models are preserved. New issues or features are gracefully integrated<br />
in existing software models, making it easy to compose software models
96 Chapter 7. Conclusions <strong>and</strong> Future Work<br />
instead of programming them. Take for example Figure 5.9, where history logging<br />
features were added to an existing class in two lter expressions, <strong>with</strong>out<br />
looking at the original class or the history logging class.<br />
Finally, wehave designed a graphical notation, in whichwe can express message<br />
passing semantics in an intuitive way. This notation, called message diagrams,<br />
is added to the pattern notations de ned by Gamma et al. (1995), so we have<br />
away toshow our modelling issues to the world.<br />
7.3 Future Work<br />
During the writing of this thesis, many thoughts have crossed the mind. It is<br />
impossible to work them all out in one thesis. We would like tomention them<br />
here, so others can elaborate on them.<br />
Pattern Implementation<br />
When implementing (applying) Software Design Patterns, we discover the following<br />
problems (Bosch 1995).<br />
Tracability The implementation does not show us explicitly that a pattern has<br />
been applied. We can see this in Appendix A.1, where we implemented<br />
the MailH<strong>and</strong>ler class as a Singleton pattern. In this implementation<br />
there is no trace of this pattern at all; only the documentation refers to<br />
it. The problem gets worse when objects participate in several patterns.<br />
The object implementation gets loaded <strong>with</strong> di erent sections belonging<br />
to di erent patterns.<br />
Implementation overhead In this same implementation we see a lot of code<br />
for just one pattern. The MailH<strong>and</strong>ler class implements several methods<br />
<strong>and</strong> de nes a class variable for the pattern. This means that every<br />
time the Singleton pattern is used, these or very similar methods will<br />
have to be written over <strong>and</strong> over.<br />
The Composition Filters Object Model can probably solve at least a part of<br />
this problem, by de ning patters <strong>and</strong> pattern roles as st<strong>and</strong>-alone software<br />
components, which can be attached to objects when appropriate. This might<br />
even be done dynamically using the Dynamic <strong>Layering</strong> Design Pattern from<br />
Section 6.3.<br />
Another way of pattern implementation has been de ned by Florijn,<br />
Meijers <strong>and</strong> van Winsen (1997). They de ne a tool which solves (a part of) the<br />
implementation overehead.<br />
Integration of Composition Filters in Java<br />
Java is becoming a very popular programming language. Unfortunately, it is<br />
based on the traditional object model, <strong>and</strong> thus has (from our point of view)<br />
the same problems as C ++.
7.3. Future Work 97<br />
It would be interesting when the Java language was extended <strong>with</strong> Composition<br />
Filters. The biggest problem for this is that Java is de ned as a very<br />
type-safe language. The use of Composition Filters introduces delegation, which<br />
intrinsically is not type-safe. It should be investigated how Composition Filters<br />
can be integrated into the Java language <strong>with</strong>out losing (too much) of its typesafety.<br />
An entry point for this can be the use of Java's interface speci cations,<br />
which in fact is an implementation of Contracts (as de ned by Helm, Holl<strong>and</strong><br />
<strong>and</strong> Gangopadhyay (1990)).<br />
Design \Improved" Versions of Existing Patterns<br />
Some of the design patterns presented by Gamma et al. (1995) can be improved<br />
by using Composition Filters. We have shown an example in this thesis<br />
already. Itwould bene t our knowledge <strong>and</strong> insights in object-oriented software<br />
modelling when other design patterns are also discussed in a similar way.<br />
Deployment of <strong>Composable</strong> Patterns<br />
A pattern is no pattern, unless it has proven itself (Gamma et al. 1995). So<br />
the patterns we have supplied in this thesis are in fact no patterns at all. They<br />
must be deployed rst. When Composition Filters are integrated in a popular<br />
development language, this will eventually happen.
98 Chapter 7. Conclusions <strong>and</strong> Future Work
Appendix A<br />
C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
A.1 Simple Mail System<br />
De nitions<br />
#ifndef MAIL H<br />
#define MAIL H<br />
class MailH<strong>and</strong>ler;<br />
class User;<br />
class Mail;<br />
class MailH<strong>and</strong>ler<br />
f<br />
public:<br />
static MailH<strong>and</strong>ler Instance(void);<br />
virtual int send(Mail );<br />
virtual char getName(void) f return name; g<br />
virtual void setName(char s) f name s; g<br />
protected:<br />
MailH<strong>and</strong>ler() fg<br />
virtual MailH<strong>and</strong>ler() fg<br />
char name;<br />
static MailH<strong>and</strong>ler instance;<br />
g;<br />
MailH<strong>and</strong>ler MailH<strong>and</strong>ler:: instance (MailH<strong>and</strong>ler )0;<br />
class User<br />
f<br />
public:<br />
virtual void setName(char s) f name s; g<br />
virtual char getName(void) f return name; g<br />
virtual void receive(Mail );<br />
(mail.hpp)<br />
99
100 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
virtual void sendSimpleMailTo(User );<br />
private:<br />
char name;<br />
g;<br />
class Mail<br />
f<br />
public:<br />
Mail();<br />
virtual void setMailOriginator(User );<br />
virtual User getMailOriginator(void);<br />
virtual void setMailReceiver(User );<br />
virtual User getMailReceiver(void);<br />
virtual void setMailContents(char );<br />
virtual char getMailContents(void);<br />
virtual void send(void);<br />
virtual void reply(void);<br />
virtual void approve(void);<br />
virtual int isApproved(void);<br />
virtual void setDelivered(void);<br />
virtual int isDelivered(void);<br />
virtual void setRoute(MailH<strong>and</strong>ler );<br />
virtual MailH<strong>and</strong>ler getRoute(void);<br />
private:<br />
User mailOriginator;<br />
User mailReceiver;<br />
char mailContents;<br />
int approved;<br />
int delivered;<br />
MailH<strong>and</strong>ler route;<br />
g;<br />
#endif<br />
Implementation<br />
#ifndef MAIN DEFINED<br />
#define MAIN DEFINED<br />
int main(void)<br />
f<br />
CALL TEST FUNCTION<br />
g<br />
#endif<br />
(main.inc)
A.1. Simple Mail System 101<br />
#undef CALL TEST FUNCTION<br />
#include <br />
#include "mail.hpp"<br />
MailH<strong>and</strong>ler<br />
MailH<strong>and</strong>ler::Instance(void)<br />
f<br />
if ( instance (MailH<strong>and</strong>ler )0) f<br />
instance new MailH<strong>and</strong>ler();<br />
instance!setName("The Only MailH<strong>and</strong>ler");<br />
g<br />
return instance;<br />
g<br />
int<br />
MailH<strong>and</strong>ler::send(Mail m)<br />
f<br />
if (m!getMailReceiver() 6= (User )0) f<br />
m!approve();<br />
g<br />
cout "=======>>>>>MailH<strong>and</strong>ler is peeking "<br />
"into the MailMessagenn"<br />
"=======>>>>>" m!getMailContents()<br />
"nn";<br />
if (m!isApproved()) f<br />
m!setRoute(this);<br />
m!setDelivered();<br />
m!getMailReceiver()!receive(m);<br />
return 0;<br />
g else f<br />
return -1;<br />
g<br />
g<br />
void<br />
User::receive(Mail m)<br />
f<br />
cout "User " this!getName()<br />
" received mail from "<br />
m!getMailOriginator()!getName()<br />
"nnRoute:ntnt" m!getRoute()!getName()<br />
"nnApproved:nt" (m!isApproved()?"Yes":"No")<br />
(mail.cc)
102 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
"nnDelivered:nt" (m!isDelivered()?"Yes":"No")<br />
"nnContents:nn----------nn"<br />
m!getMailContents()<br />
"nn----------nn";<br />
void<br />
User::sendSimpleMailTo(User u)<br />
f<br />
Mail mailMessage new Mail();<br />
mailMessage!setMailOriginator(this);<br />
mailMessage!setMailReceiver(u);<br />
mailMessage!setMailContents(<br />
"Contents of a simple mail message");<br />
mailMessage!send();<br />
g<br />
Mail::Mail()<br />
f<br />
mailOriginator (User )0;<br />
mailReceiver (User )0;<br />
mailContents (char )0;<br />
approved 0;<br />
delivered 0;<br />
route (MailH<strong>and</strong>ler )0;<br />
g<br />
void<br />
Mail::setMailOriginator(User u)<br />
f<br />
mailOriginator u;<br />
g<br />
User<br />
Mail::getMailOriginator(void)<br />
f<br />
return mailOriginator;<br />
g<br />
void<br />
Mail::setMailReceiver(User u)<br />
f<br />
mailReceiver u;<br />
g
A.1. Simple Mail System 103<br />
User<br />
Mail::getMailReceiver(void)<br />
f<br />
return mailReceiver;<br />
g<br />
void<br />
Mail::setMailContents(char s)<br />
f<br />
mailContents s;<br />
g<br />
char<br />
Mail::getMailContents(void)<br />
f<br />
return mailContents;<br />
g<br />
void<br />
Mail::send(void)<br />
f<br />
MailH<strong>and</strong>ler::Instance()!send(this);<br />
g<br />
void<br />
Mail::reply(void)<br />
f<br />
g<br />
void<br />
Mail::approve(void)<br />
f<br />
approved 1;<br />
g<br />
int<br />
Mail::isApproved(void)<br />
f<br />
return approved;<br />
g<br />
void<br />
Mail::setDelivered(void)
104 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
f<br />
g<br />
delivered 1;<br />
int<br />
Mail::isDelivered(void)<br />
f<br />
return delivered;<br />
g<br />
void<br />
Mail::setRoute(MailH<strong>and</strong>ler mh)<br />
f<br />
route mh;<br />
g<br />
MailH<strong>and</strong>ler<br />
Mail::getRoute(void)<br />
f<br />
return route;<br />
g<br />
#define CALL TEST FUNCTION test simple mail();<br />
void test simple mail(void)<br />
f<br />
cout "SimpleMail testnn";<br />
User u1 new User();<br />
u1!setName("MailOriginator");<br />
User u2 new User();<br />
u2!setName("MailReceiver");<br />
u1!sendSimpleMailTo(u2);<br />
g<br />
#include "main.inc"<br />
A.2 UserSystemView Mail System<br />
De nitions<br />
#ifndef USVMAIL H<br />
#define USVMAIL H<br />
#include "mail.hpp"<br />
(usvmail.hpp)
A.2. UserSystemView Mail System 105<br />
class MVUser;<br />
class MVMailH<strong>and</strong>ler;<br />
class UserSystemViewMail;<br />
#define CFilter(A,B) if (A)fB;gelsefcout "Filter error";g<br />
typedef enum f<br />
ObjectClass,<br />
MVMailH<strong>and</strong>lerClass,<br />
MVUserClass,<br />
GroupUserClass,<br />
PGPUserClass,<br />
ProtectedUserClass,<br />
UserSystemViewMailClass,<br />
OriginatorReceiverViewMailClass,<br />
GroupMailClass,<br />
SecureMailClass,<br />
Warning2MailClass,<br />
ProtectedMailClass,<br />
lastClass<br />
g classTypes;<br />
class Object<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return ObjectClass; g<br />
virtual int isKindOf(classTypes ct) f return this!myClass() ct; g<br />
virtual char asString(void) f return this!className(); g<br />
virtual char className(void) f return "Object"; g<br />
g;<br />
class MVMailH<strong>and</strong>ler : public MailH<strong>and</strong>ler, public Object<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return MVMailH<strong>and</strong>lerClass; g<br />
virtual int send(UserSystemViewMail );<br />
static MVMailH<strong>and</strong>ler Instance(void);<br />
virtual char className(void) f return "MVMailH<strong>and</strong>ler"; g<br />
protected:<br />
MVMailH<strong>and</strong>ler() fg<br />
virtual MVMailH<strong>and</strong>ler() fg<br />
static MVMailH<strong>and</strong>ler instance;<br />
g;
106 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
MVMailH<strong>and</strong>ler MVMailH<strong>and</strong>ler:: instance (MVMailH<strong>and</strong>ler )0;<br />
class MVUser : public User, public Object<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return MVUserClass; g<br />
virtual void receive(UserSystemViewMail );<br />
virtual void sendUserSystemViewMailTo(MVUser u);<br />
virtual char className(void) f return "MVUser"; g<br />
g;<br />
class UserSystemViewMail : public Object f<br />
public:<br />
UserSystemViewMail();<br />
virtual UserSystemViewMail();<br />
virtual classTypes myClass(void) f return UserSystemViewMailClass;<br />
g<br />
virtual void setMailOriginator(Object ,MVUser );<br />
virtual MVUser getMailOriginator(Object );<br />
virtual void setMailReceiver(Object ,MVUser );<br />
virtual MVUser getMailReceiver(Object );<br />
virtual void setMailContents(Object ,char );<br />
virtual char getMailContents(Object );<br />
virtual void send(Object );<br />
virtual void reply(Object );<br />
virtual void approve(Object );<br />
virtual int isApproved(Object );<br />
virtual void setDelivered(Object );<br />
virtual int isDelivered(Object );<br />
virtual void setRoute(Object ,MVMailH<strong>and</strong>ler );<br />
virtual MVMailH<strong>and</strong>ler getRoute(Object );<br />
virtual char className(void) f return "UserSystemViewMail"; g<br />
protected:<br />
virtual int isUserView(Object );<br />
virtual int isSystemView(Object );<br />
private:<br />
Mail mail;<br />
virtual void pureSetMailOriginator(MVUser );<br />
virtual MVUser pureGetMailOriginator(void);<br />
virtual void pureSetMailReceiver(MVUser );<br />
virtual MVUser pureGetMailReceiver(void);<br />
virtual void pureSetMailContents(char );<br />
virtual char pureGetMailContents(void);<br />
virtual void pureSend(void);
A.2. UserSystemView Mail System 107<br />
g;<br />
#endif<br />
virtual void pureReply(void);<br />
virtual void pureApprove(void);<br />
virtual int pureIsApproved(void);<br />
virtual void pureSetDelivered(void);<br />
virtual int pureIsDelivered(void);<br />
virtual void pureSetRoute(MVMailH<strong>and</strong>ler );<br />
virtual MVMailH<strong>and</strong>ler pureGetRoute(void);<br />
Implementation<br />
#include <br />
#include <br />
#include "usvmail.hpp"<br />
MVMailH<strong>and</strong>ler<br />
MVMailH<strong>and</strong>ler::Instance(void)<br />
f<br />
if ( instance (MVMailH<strong>and</strong>ler )0) f<br />
instance new MVMailH<strong>and</strong>ler();<br />
instance!setName("The Only MVMailH<strong>and</strong>ler");<br />
g<br />
return (MVMailH<strong>and</strong>ler ) instance;<br />
g<br />
int<br />
MVMailH<strong>and</strong>ler::send(UserSystemViewMail m)<br />
f<br />
if (m!getMailReceiver(this) 6= (MVUser )0) f<br />
m!approve(this);<br />
g<br />
cout "=======>>>>>MVMailH<strong>and</strong>ler is peeking "<br />
"into the MailMessagenn"<br />
"=======>>>>>" m!getMailContents(this)<br />
"nn";<br />
if (m!isApproved(this)) f<br />
m!setRoute(this,this);<br />
m!setDelivered(this);<br />
m!getMailReceiver(this)!receive(m);<br />
return 0;<br />
g else f<br />
(usvmail.cc)
108 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
g<br />
return -1;<br />
void<br />
MVUser::receive(UserSystemViewMail m)<br />
f<br />
cout "User " this!getName()<br />
" received mail from "<br />
m!getMailOriginator(this)!getName()<br />
"nnRoute:ntnt" m!getRoute(this)!getName()<br />
"nnApproved:nt" (m!isApproved(this)?"Yes":"No")<br />
"nnDelivered:nt"<br />
(m!isDelivered(this)?"Yes":"No")<br />
"nnContents:nn----------nn"<br />
m!getMailContents(this)<br />
"nn----------nn";<br />
g<br />
void<br />
MVUser::sendUserSystemViewMailTo(MVUser u)<br />
f<br />
UserSystemViewMail mailMessage new UserSystemViewMail();<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailContents(this,<br />
"Contents of a UserSystemView mail message");<br />
mailMessage!send(this);<br />
g<br />
UserSystemViewMail::UserSystemViewMail()<br />
f<br />
mail new Mail();<br />
assert( mail 6= (Mail )0);<br />
g<br />
UserSystemViewMail:: UserSystemViewMail()<br />
f<br />
delete mail;<br />
g<br />
void<br />
UserSystemViewMail::pureSetMailOriginator(MVUser u)<br />
f
A.2. UserSystemView Mail System 109<br />
g<br />
mail!setMailOriginator(u);<br />
MVUser<br />
UserSystemViewMail::pureGetMailOriginator(void)<br />
f<br />
return (MVUser ) mail!getMailOriginator();<br />
g<br />
void<br />
UserSystemViewMail::pureSetMailReceiver(MVUser u)<br />
f<br />
mail!setMailReceiver(u);<br />
g<br />
MVUser<br />
UserSystemViewMail::pureGetMailReceiver(void)<br />
f<br />
return (MVUser ) mail!getMailReceiver();<br />
g<br />
void<br />
UserSystemViewMail::pureSetMailContents(char s)<br />
f<br />
mail!setMailContents(s);<br />
g<br />
char<br />
UserSystemViewMail::pureGetMailContents(void)<br />
f<br />
return mail!getMailContents();<br />
g<br />
void<br />
UserSystemViewMail::pureSend(void)<br />
f<br />
MVMailH<strong>and</strong>ler::Instance()!send(this);<br />
g<br />
void<br />
UserSystemViewMail::pureReply(void)<br />
f<br />
mail!reply();<br />
g
110 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
void<br />
UserSystemViewMail::pureApprove(void)<br />
f<br />
mail!approve();<br />
g<br />
int<br />
UserSystemViewMail::pureIsApproved(void)<br />
f<br />
return mail!isApproved();<br />
g<br />
void<br />
UserSystemViewMail::pureSetDelivered(void)<br />
f<br />
mail!setDelivered();<br />
g<br />
int<br />
UserSystemViewMail::pureIsDelivered(void)<br />
f<br />
return mail!isDelivered();<br />
g<br />
void<br />
UserSystemViewMail::pureSetRoute(MVMailH<strong>and</strong>ler mh)<br />
f<br />
mail!setRoute(mh);<br />
g<br />
MVMailH<strong>and</strong>ler<br />
UserSystemViewMail::pureGetRoute(void)<br />
f<br />
return (MVMailH<strong>and</strong>ler ) mail!getRoute();<br />
g<br />
int<br />
UserSystemViewMail::isUserView(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return sender!isKindOf(MVUserClass);<br />
g
A.2. UserSystemView Mail System 111<br />
int<br />
UserSystemViewMail::isSystemView(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return sender!isKindOf(MVMailH<strong>and</strong>lerClass);<br />
g<br />
void<br />
UserSystemViewMail::setMailOriginator(Object sender,MVUser u)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender),this!pureSetMailOriginator(u));<br />
g<br />
MVUser<br />
UserSystemViewMail::getMailOriginator(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return pureGetMailOriginator();<br />
g<br />
void<br />
UserSystemViewMail::setMailReceiver(Object sender,MVUser u)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender),this!pureSetMailReceiver(u));<br />
g<br />
MVUser<br />
UserSystemViewMail::getMailReceiver(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return pureGetMailReceiver();<br />
g<br />
void<br />
UserSystemViewMail::setMailContents(Object sender,char s)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender),this!pureSetMailContents(s));<br />
g<br />
char<br />
UserSystemViewMail::getMailContents(Object sender)
112 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
f<br />
g<br />
char s (char )0;<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender),s this!pureGetMailContents());<br />
return s;<br />
void<br />
UserSystemViewMail::send(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender),this!pureSend());<br />
g<br />
void<br />
UserSystemViewMail::reply(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isUserView(sender),this!pureReply());<br />
g<br />
void<br />
UserSystemViewMail::approve(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isSystemView(sender),this!pureApprove());<br />
g<br />
int<br />
UserSystemViewMail::isApproved(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return this!pureIsApproved();<br />
g<br />
void<br />
UserSystemViewMail::setDelivered(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isSystemView(sender),this!pureSetDelivered());<br />
g<br />
int<br />
UserSystemViewMail::isDelivered(Object sender)
A.3. OriginatorReceiverView Mail System 113<br />
f<br />
g<br />
assert(sender6=(Object )0);<br />
return this!pureIsDelivered();<br />
void<br />
UserSystemViewMail::setRoute(Object sender,MVMailH<strong>and</strong>ler mh)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isSystemView(sender),this!pureSetRoute(mh));<br />
g<br />
MVMailH<strong>and</strong>ler<br />
UserSystemViewMail::getRoute(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return this!pureGetRoute();<br />
g<br />
#define CALL TEST FUNCTION test usersystemview mail();<br />
void test usersystemview mail(void)<br />
f<br />
cout "UserSystemViewMail testnn";<br />
MVUser u1 new MVUser();<br />
u1!setName("MailOriginator");<br />
MVUser u2 new MVUser();<br />
u2!setName("MailReceiver");<br />
u1!sendUserSystemViewMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "mail.cc"<br />
A.3 OriginatorReceiverView Mail System<br />
De nitions<br />
#ifndef ORVMAIL H<br />
#define ORVMAIL H<br />
#include "usvmail.hpp"<br />
(orvmail.hpp)
114 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
class VPUser : public MVUser<br />
f<br />
public:<br />
virtual void sendOriginatorReceiverViewMailTo(MVUser );<br />
g;<br />
class OriginatorReceiverViewMail : public UserSystemViewMail<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return<br />
OriginatorReceiverViewMailClass; g<br />
virtual void setMailOriginator(Object ,MVUser );<br />
virtual void setMailReceiver(Object ,MVUser );<br />
virtual void setMailContents(Object ,char );<br />
virtual char getMailContents(Object );<br />
virtual void send(Object );<br />
virtual void reply(Object );<br />
protected:<br />
virtual int isOriginatorView(Object );<br />
virtual int isReceiverView(Object );<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include <br />
#include "orvmail.hpp"<br />
(orvmail.cc)<br />
void<br />
VPUser::sendOriginatorReceiverViewMailTo(MVUser u)<br />
f<br />
OriginatorReceiverViewMail mailMessage new<br />
OriginatorReceiverViewMail();<br />
VPUser sneakUser new VPUser();<br />
sneakUser!setName("Sneaky User");<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailContents(this,<br />
"Contents of a OriginatorReceiverView Mail Message");<br />
mailMessage!send(this);<br />
sneakUser!receive(mailMessage);
A.3. OriginatorReceiverView Mail System 115<br />
g<br />
int<br />
OriginatorReceiverViewMail::isOriginatorView(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return (this!getMailOriginator(this) (MVUser )0)<br />
jj sender this!getMailOriginator(this);<br />
g<br />
int<br />
OriginatorReceiverViewMail::isReceiverView(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
return sender this!getMailReceiver(this);<br />
g<br />
void<br />
OriginatorReceiverViewMail::setMailOriginator(Object sender,MVUser u)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isOriginatorView(sender),<br />
UserSystemViewMail::setMailOriginator(sender,u));<br />
g<br />
void<br />
OriginatorReceiverViewMail::setMailReceiver(Object sender,MVUser u)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isOriginatorView(sender),<br />
UserSystemViewMail::setMailReceiver(sender,u));<br />
g<br />
void<br />
OriginatorReceiverViewMail::setMailContents(Object sender,char s)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isOriginatorView(sender),<br />
UserSystemViewMail::setMailContents(sender,s));<br />
g<br />
char<br />
OriginatorReceiverViewMail::getMailContents(Object sender)<br />
f
116 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
char s (char )0;<br />
assert(sender6=(Object )0);<br />
CFilter(this!isOriginatorView(sender)<br />
jj this!isReceiverView(sender),<br />
s UserSystemViewMail::getMailContents(sender));<br />
return s;<br />
void<br />
OriginatorReceiverViewMail::send(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isOriginatorView(sender),<br />
UserSystemViewMail::send(sender));<br />
g<br />
void<br />
OriginatorReceiverViewMail::reply(Object sender)<br />
f<br />
assert(sender6=(Object )0);<br />
CFilter(this!isReceiverView(sender),<br />
UserSystemViewMail::reply(sender));<br />
g<br />
#define CALL TEST FUNCTION test originatorreceiverview mail();<br />
void test originatorreceiverview mail(void)<br />
f<br />
cout "OriginatorReceiverViewMail testnn";<br />
VPUser u1 new VPUser();<br />
u1!setName("MailOriginator");<br />
VPUser u2 new VPUser();<br />
u2!setName("MailReceiver");<br />
u1!sendOriginatorReceiverViewMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "usvmail.cc"<br />
A.4 Group Mail System<br />
De nitions<br />
(gmail.hpp)
A.4. Group Mail System 117<br />
#ifndef GMAIL H<br />
#define GMAIL H<br />
#include "orvmail.hpp"<br />
class GroupUser: public VPUser<br />
f<br />
public:<br />
GroupUser() f groupNumber 0; g<br />
virtual classTypes myClass(void) f return GroupUserClass; g<br />
virtual void sendGroupMailTo(MVUser );<br />
virtual void setGroup(int i) f groupNumber i; g<br />
virtual int getGroup(void) f return groupNumber; g<br />
virtual int isKindOf(classTypes ct) f return ((ct MVUserClass) jj<br />
VPUser::isKindOf(ct)); g<br />
protected:<br />
int groupNumber;<br />
g;<br />
class GroupMail : public OriginatorReceiverViewMail<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return GroupMailClass; g<br />
protected:<br />
virtual int isOriginatorView(Object );<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include <br />
#include "gmail.hpp"<br />
void<br />
GroupUser::sendGroupMailTo(MVUser u)<br />
f<br />
GroupMail mailMessage new GroupMail();<br />
GroupUser groupMember new GroupUser();<br />
groupMember!setName("GroupMember of MailOriginator");<br />
groupMember!setGroup(100);<br />
this!setGroup(100);<br />
(gmail.cc)
118 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailContents(this,<br />
"Contents of a Group Mail Message");<br />
mailMessage!send(this);<br />
groupMember!receive(mailMessage);<br />
int<br />
GroupMail::isOriginatorView(Object sender)<br />
f<br />
MVUser orig this!getMailOriginator(this);<br />
assert(sender6=(Object )0);<br />
return (orig (MVUser )0)<br />
jj sender orig<br />
jj (sender!isKindOf(GroupUserClass) &&<br />
orig!isKindOf(GroupUserClass)<br />
&& ((GroupUser )sender)!getGroup()<br />
((GroupUser )orig)!getGroup());<br />
g<br />
#define CALL TEST FUNCTION test group mail();<br />
void test group mail(void)<br />
f<br />
cout "Group Mail testnn";<br />
GroupUser u1 new GroupUser();<br />
u1!setName("MailOriginator");<br />
GroupUser u2 new GroupUser();<br />
u2!setName("MailReceiver");<br />
u1!sendGroupMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "orvmail.cc"<br />
A.5 Secure Mail System<br />
De nitions<br />
#ifndef SMAIL H<br />
#define SMAIL H<br />
(smail.hpp)
A.5. Secure Mail System 119<br />
#include "gmail.hpp"<br />
class PGPUser : public GroupUser<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return PGPUserClass; g<br />
virtual int isKindOf(classTypes ct) f return (ct GroupUserClass jj<br />
GroupUser::isKindOf(ct)); g<br />
virtual void setPGPPubKey(int i) f publicKey i; g<br />
virtual int getPGPPubKey(void) f return publicKey; g<br />
virtual void setPGPPrivKey(int i) f privateKey i; g<br />
virtual int getPGPPrivKey(void) f return privateKey; g<br />
virtual void sendSecureMailTo(MVUser );<br />
private:<br />
int publicKey;<br />
int privateKey;<br />
g;<br />
class SecureMail : public GroupMail<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return SecureMailClass; g<br />
virtual char getMailContents(Object );<br />
virtual void setMailContents(Object , char );<br />
protected:<br />
virtual int isPGPUserView(Object );<br />
private:<br />
virtual char purePGPGetMailContents(Object );<br />
virtual void purePGPSetMailContents(Object , char );<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include <br />
#include "smail.hpp"<br />
void<br />
PGPUser::sendSecureMailTo(MVUser u)<br />
f<br />
SecureMail mailMessage new SecureMail();<br />
(smail.cc)
120 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
GroupUser nonPGPUser new GroupUser();<br />
nonPGPUser!setName("NON PGP USER");<br />
nonPGPUser!setGroup(100);<br />
this!setGroup(100);<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailContents(this,<br />
"Contents of a Secure Mail Message");<br />
mailMessage!send(this);<br />
nonPGPUser!receive(mailMessage);<br />
int<br />
SecureMail::isPGPUserView(Object sender)<br />
f<br />
return sender!isKindOf(PGPUserClass);<br />
g<br />
char<br />
SecureMail::getMailContents(Object sender)<br />
f<br />
char s (char )0;<br />
if (this!isPGPUserView(sender)) f<br />
s this!purePGPGetMailContents(sender);<br />
g else f<br />
s GroupMail::getMailContents(sender);<br />
g<br />
return s;<br />
g<br />
void<br />
SecureMail::setMailContents(Object sender,char s)<br />
f<br />
if (this!isPGPUserView(sender)) f<br />
this!purePGPSetMailContents(sender,s);<br />
g else f<br />
GroupMail::setMailContents(sender,s);<br />
g<br />
g<br />
char<br />
SecureMail::purePGPGetMailContents(Object sender)<br />
f<br />
char l, s strdup(GroupMail::getMailContents(sender));
A.6. Warning2 Mail System 121<br />
g<br />
cout "PGP decoding...nn";<br />
for (l s; l;l++) ( l)--;<br />
return s;<br />
void<br />
SecureMail::purePGPSetMailContents(Object sender, char s)<br />
f<br />
char l, c strdup(s);<br />
cout "PGP encoding...nn";<br />
for (l c; l;l++) ( l)++;<br />
GroupMail::setMailContents(sender,c);<br />
g<br />
#define CALL TEST FUNCTION test secure mail();<br />
void test secure mail(void)<br />
f<br />
cout "Secure Mail testnn";<br />
PGPUser u1 new PGPUser();<br />
u1!setName("MailOriginator");<br />
PGPUser u2 new PGPUser();<br />
u2!setName("MailReceiver");<br />
u1!sendSecureMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "gmail.cc"<br />
A.6 Warning2 Mail System<br />
De nitions<br />
#ifndef W2MAIL H<br />
#define W2MAIL H<br />
#include "smail.hpp"<br />
typedef enum f<br />
W2MailSetMailContentsSelector,<br />
W2MailSetMailOriginatorSelector,<br />
W2MailSetMailReceiverSelector,<br />
W2MailSendSelector,<br />
(w2mail.hpp)
122 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
lastWarning2MailSelector<br />
g Warning2MailSelector;<br />
class Warning2User : public PGPUser<br />
f<br />
public:<br />
virtual void sendWarning2MailTo(MVUser );<br />
g;<br />
class Warning2Mail : public SecureMail<br />
f<br />
public:<br />
Warning2Mail();<br />
virtual classTypes myClass(void) f return Warning2MailClass; g<br />
virtual void setMailContents(Object ,char );<br />
virtual void setMailOriginator(Object , MVUser );<br />
virtual void setMailReceiver(Object , MVUser );<br />
virtual void send(Object );<br />
protected:<br />
virtual int isWarning2View(Warning2MailSelector);<br />
private:<br />
int selectorCount[ lastWarning2MailSelector];<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include "w2mail.hpp"<br />
void<br />
Warning2User::sendWarning2MailTo(MVUser u)<br />
f<br />
Warning2Mail mailMessage new Warning2Mail();<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailContents(this,<br />
"First contents of a Warning2 Mail Message");<br />
mailMessage!setMailContents(this,<br />
"Second contents of a Warning2 Mail Message");<br />
(w2mail.cc)
A.6. Warning2 Mail System 123<br />
g<br />
mailMessage!send(this);<br />
Warning2Mail::Warning2Mail()<br />
f<br />
int i;<br />
for (i 0;i< lastWarning2MailSelector;i++)<br />
selectorCount[i] 0;<br />
g<br />
int<br />
Warning2Mail::isWarning2View(Warning2MailSelector sel)<br />
f<br />
return selectorCount[sel] > 0;<br />
g<br />
void<br />
Warning2Mail::setMailContents(Object sender, char s)<br />
f<br />
if (this!isWarning2View(W2MailSetMailContentsSelector)) f<br />
cout "Warning, setMailContents sent twicenn";<br />
g<br />
selectorCount[W2MailSetMailContentsSelector]++;<br />
SecureMail::setMailContents(sender,s);<br />
g<br />
void<br />
Warning2Mail::setMailOriginator(Object sender, MVUser u)<br />
f<br />
if (this!isWarning2View(W2MailSetMailOriginatorSelector)) f<br />
cout "Warning, setMailOriginator sent twicenn";<br />
g<br />
selectorCount[W2MailSetMailOriginatorSelector]++;<br />
SecureMail::setMailOriginator(sender,u);<br />
g<br />
void<br />
Warning2Mail::setMailReceiver(Object sender, MVUser u)<br />
f<br />
if (this!isWarning2View(W2MailSetMailReceiverSelector)) f<br />
cout "Warning, setMailReceiver sent twicenn";<br />
g<br />
selectorCount[W2MailSetMailReceiverSelector]++;<br />
SecureMail::setMailReceiver(sender,u);
124 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
void<br />
Warning2Mail::send(Object sender)<br />
f<br />
if (this!isWarning2View(W2MailSendSelector)) f<br />
cout "Warning, send sent twicenn";<br />
g<br />
selectorCount[W2MailSendSelector]++;<br />
SecureMail::send(sender);<br />
g<br />
#define CALL TEST FUNCTION test w2 mail();<br />
void test w2 mail(void)<br />
f<br />
cout "w2 Mail testnn";<br />
Warning2User u1 new Warning2User();<br />
u1!setName("MailOriginator");<br />
Warning2User u2 new Warning2User();<br />
u2!setName("MailReceiver");<br />
u1!sendWarning2MailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "smail.cc"<br />
A.7 Protected Mail System<br />
De nitions<br />
#ifndef PMAIL H<br />
#define PMAIL H<br />
#include "w2mail.hpp"<br />
class SecureDocument:public Object f<br />
public:<br />
virtual void setSecurityLevel(int);<br />
virtual int getSecurityLevel(void);<br />
protected:<br />
int isSecurityClearance(Object );<br />
private:<br />
(pmail.hpp)
A.7. Protected Mail System 125<br />
g;<br />
int securityLevel;<br />
class ProtectedUser : public Warning2User<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return ProtectedUserClass; g<br />
virtual int getSecurityLevel(void);<br />
virtual void setSecurityLevel(int);<br />
virtual void sendProtectedMailTo(MVUser );<br />
virtual int isKindOf(classTypes ct) f return ((ct PGPUserClass) jj<br />
Warning2User::isKindOf(ct)); g<br />
private:<br />
int securityLevel;<br />
g;<br />
class ProtectedMail : public Warning2Mail, public SecureDocument<br />
f<br />
public:<br />
virtual classTypes myClass(void) f return ProtectedMailClass; g<br />
virtual void setMailContents(Object ,char );<br />
virtual char getMailContents(Object );<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include "pmail.hpp"<br />
void<br />
SecureDocument::setSecurityLevel(int i) f<br />
securityLevel i;<br />
g<br />
int<br />
SecureDocument::getSecurityLevel(void) f<br />
return securityLevel;<br />
g<br />
int<br />
SecureDocument::isSecurityClearance(Object sender) f<br />
(pmail.cc)
126 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
g<br />
return (sender!isKindOf(ProtectedUserClass)) &&<br />
(((ProtectedUser )sender)!getSecurityLevel()<br />
this!getSecurityLevel());<br />
void<br />
ProtectedUser::setSecurityLevel(int i) f<br />
securityLevel i;<br />
g<br />
int<br />
ProtectedUser::getSecurityLevel(void) f<br />
return securityLevel;<br />
g<br />
void<br />
ProtectedUser::sendProtectedMailTo(MVUser u)<br />
f<br />
ProtectedMail mailMessage new ProtectedMail();<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setSecurityLevel(3);<br />
mailMessage!setMailContents(this,<br />
"Contents of a Protected Mail Message");<br />
mailMessage!send(this);<br />
mailMessage!setSecurityLevel(1);<br />
mailMessage!send(this);<br />
g<br />
void<br />
ProtectedMail::setMailContents(Object sender, char s)<br />
f<br />
CFilter(this!isSecurityClearance(sender),<br />
Warning2Mail::setMailContents(sender,s));<br />
g<br />
char<br />
ProtectedMail::getMailContents(Object sender)<br />
f<br />
char s (char )0;<br />
CFilter(this!isSecurityClearance(sender),s<br />
Warning2Mail::getMailContents(sender));<br />
return s;<br />
g
A.7. Protected Mail System 127<br />
#define CALL TEST FUNCTION test protected mail();<br />
void test protected mail(void)<br />
f<br />
cout "Protected Mail testnn";<br />
ProtectedUser u1 new ProtectedUser();<br />
u1!setName("MailOriginator");<br />
u1!setSecurityLevel(4);<br />
ProtectedUser u2 new ProtectedUser();<br />
u2!setName("MailReceiver");<br />
u2!setSecurityLevel(2);<br />
u1!sendProtectedMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "w2mail.cc"
128 Appendix A. C ++ Implementation of <strong>Multiple</strong> <strong>Views</strong>
Appendix B<br />
Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
B.1 Simple Mail System<br />
#NoDefSyncFilter;<br />
class MailH<strong>and</strong>ler interface<br />
methods<br />
send (aMailMessage : Mail) returns nil;<br />
getName returns String;<br />
setName (aName : String) returns nil;<br />
input lters<br />
dis : Dispatch =f inner. g;<br />
end;<br />
class MailH<strong>and</strong>ler implementation<br />
instvars<br />
name : String;<br />
initial<br />
begin<br />
name 'NoName'<br />
end;<br />
methods<br />
send (aMailMessage : Mail)<br />
begin<br />
return;<br />
if aMailMessage.getMailReceiver 6= nil<br />
then<br />
aMailMessage.approve<br />
end;<br />
server.printLine('Peeking into the MailMessage');<br />
server.printLine(aMailMessage.getMailContents);<br />
if aMailMessage.isApproved<br />
then<br />
(MailH<strong>and</strong>ler.sina)<br />
129
130 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
aMailMessage.setRoute(server);<br />
aMailMessage.setDelivered;<br />
aMailMessage.getMailReceiver.receive(aMailMessage)<br />
end<br />
end;<br />
getName<br />
begin<br />
return name<br />
end;<br />
setName (aName : String)<br />
begin<br />
name aName<br />
end;<br />
end;<br />
class User interface<br />
methods<br />
setName (aName : String) returns nil;<br />
getName returns String;<br />
receive (aMailMessage : Mail) returns nil;<br />
sendSimpleMailTo (aUser : User) returns nil;<br />
input lters<br />
dis : Dispatch =f inner. g;<br />
end;<br />
class User implementation<br />
instvars<br />
name : String;<br />
initial<br />
begin<br />
name 'NoName'<br />
end;<br />
methods<br />
setName (aName : String)<br />
begin<br />
name aName<br />
end;<br />
getName<br />
begin<br />
return name<br />
end;<br />
receive (aMailMessage : Mail)<br />
begin<br />
(User.sina)
B.1. Simple Mail System 131<br />
return;<br />
server.print('User ');<br />
server.print(server.getName);<br />
server.print(' received mail from ');<br />
server.printLine(aMailMessage.getMailOriginator.getName);<br />
server.print('Route: ');<br />
server.printLine(aMailMessage.getRoute.getName);<br />
server.print('Approved: ');<br />
server.printLine(aMailMessage.isApproved);<br />
server.print('Delivered: ');<br />
server.printLine(aMailMessage.isDelivered);<br />
server.print('Contents:');<br />
server.printLine(aMailMessage.getMailContents);<br />
end;<br />
sendSimpleMailTo (aUser : User)<br />
temps<br />
aMailMessage : Mail;<br />
begin<br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a simple mail message');<br />
aMailMessage.send<br />
end;<br />
end;<br />
class Mail interface<br />
externals<br />
MH : MailH<strong>and</strong>ler;<br />
methods<br />
setMailOriginator (aUser : User) returns nil;<br />
getMailOriginator returns User;<br />
setMailReceiver (aUser : User) returns nil;<br />
getMailReceiver returns User;<br />
setMailContents (aString : String) returns nil;<br />
getMailContents returns String;<br />
send returns nil;<br />
reply returns nil;<br />
approve returns nil;<br />
isApproved returns Boolean;<br />
setDelivered returns nil;<br />
isDelivered returns Boolean;<br />
setRoute (aMH : MailH<strong>and</strong>ler) returns nil;<br />
(Mail.sina)
132 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
getRoute returns MailH<strong>and</strong>ler;<br />
input lters<br />
dis : Dispatch =f inner. g;<br />
end;<br />
class Mail implementation<br />
instvars<br />
mailOriginator : User;<br />
mailReceiver : User;<br />
mailContents : String;<br />
approved : Boolean;<br />
delivered : Boolean;<br />
route : MailH<strong>and</strong>ler;<br />
initial<br />
begin<br />
mailOriginator nil;<br />
mailReceiver nil;<br />
mailContents '';<br />
approved false;<br />
delivered false;<br />
route nil<br />
end;<br />
methods<br />
setMailOriginator (aUser : User)<br />
begin<br />
mailOriginator aUser<br />
end;<br />
getMailOriginator<br />
begin<br />
return mailOriginator<br />
end;<br />
setMailReceiver (aUser : User)<br />
begin<br />
mailReceiver aUser<br />
end;<br />
getMailReceiver<br />
begin<br />
return mailReceiver<br />
end;<br />
setMailContents (aString : String)<br />
begin<br />
mailContents aString<br />
end;<br />
getMailContents
B.1. Simple Mail System 133<br />
begin<br />
return mailContents<br />
end;<br />
send<br />
begin<br />
MH.send(server)<br />
end;<br />
reply<br />
begin<br />
server.print('Not implemented')<br />
end;<br />
approve<br />
begin<br />
approved true<br />
end;<br />
isApproved<br />
begin<br />
return approved<br />
end;<br />
setDelivered<br />
begin<br />
delivered true<br />
end;<br />
isDelivered<br />
begin<br />
return delivered<br />
end;<br />
setRoute (aMH : MailH<strong>and</strong>ler)<br />
begin<br />
route aMH<br />
end;<br />
getRoute<br />
begin<br />
return route<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : User;<br />
u2 : User;<br />
begin<br />
u1.setName('MailOriginator');<br />
(MailMain.sina)
134 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
end<br />
u2.setName('MailReceiver');<br />
u1.sendSimpleMailTo(u2);<br />
B.2 UserSystemView Mail System<br />
(UserSystemViewMail.sina)<br />
class UserSystemViewMail interface<br />
externals<br />
User : Class;<br />
MailH<strong>and</strong>ler : Class;<br />
internals<br />
mail : Mail;<br />
conditions<br />
userView;<br />
systemView;<br />
input lters<br />
mv1 : Error = f userView ) setMailOriginator,<br />
true ; setMailOriginator g;<br />
mv2 : Error = f userView ) setMailReceiver, true ; setMailReceiver g;<br />
mv3 : Error = f userView ) setMailContents,<br />
true ; setMailContents g;<br />
mv4 : Error = f userView ) getMailContents,<br />
true ; getMailContents g;<br />
mv5 : Error = f userView ) send, true ; send g;<br />
mv6 : Error = f userView ) reply, true ; reply g;<br />
mv7 : Error = f systemView ) approve, true ; approve g;<br />
mv8 : Error = f systemView ) setDelivered, true ; setDelivered g;<br />
mv9 : Error = f systemView ) setRoute, true ; setRoute g;<br />
disp : Dispatch =f inner. , mail. g;<br />
end;<br />
class UserSystemViewMail implementation<br />
conditions<br />
userView<br />
begin<br />
return message.sender.isKindOf:(User)<br />
end;<br />
systemView<br />
begin<br />
return message.sender.isKindOf:(MailH<strong>and</strong>ler)<br />
end;<br />
end;
B.3. OriginatorReceiverView Mail System 135<br />
class MVUser interface<br />
internals<br />
user : User;<br />
methods<br />
sendUserSystemViewMailTo (aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class MVUser implementation<br />
methods<br />
sendUserSystemViewMailTo (aUser : User)<br />
temps<br />
aMailMessage : UserSystemViewMail;<br />
begin<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a UserSystem Mail Message');<br />
aMailMessage.send<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : MVUser;<br />
u2 : MVUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendUserSystemViewMailTo(u2);<br />
end<br />
B.3 OriginatorReceiverView Mail System<br />
class OriginatorReceiverViewMail interface<br />
externals<br />
User : Class;<br />
MailH<strong>and</strong>ler : Class;<br />
internals<br />
(MVUser.sina)<br />
(UserSystemViewMailMain.sina)<br />
(OriginatorReceiverViewMail.sina)
136 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
mail : UserSystemViewMail;<br />
conditions<br />
originatorView;<br />
receiverView;<br />
input lters<br />
mv1 : Error = f originatorView ) setMailOriginator,<br />
true ; setMailOriginator g;<br />
mv2 : Error = f originatorView ) setMailReceiver,<br />
true ; setMailReceiver g;<br />
mv3 : Error = f originatorView ) setMailContents<br />
true ; setMailContents g;<br />
mv4 : Error = f originatorView ) getMailContents,<br />
receiverView ) getMailContents,<br />
true ; getMailContents g;<br />
mv5 : Error = f originatorView ) send, true ; send g;<br />
mv6 : Error = f receiverView ) reply, true ; reply g;<br />
disp : Dispatch =f inner. , mail. g;<br />
end;<br />
class OriginatorReceiverViewMail implementation<br />
conditions<br />
originatorView<br />
begin<br />
return (mail.getMailOriginator nil)<br />
jj (mail.getMailOriginator message.sender);<br />
end;<br />
receiverView<br />
begin<br />
return mail.getMailReceiver message.sender<br />
end;<br />
end;<br />
class VPUser interface<br />
internals<br />
user : MVUser;<br />
methods<br />
sendOriginatorReceiverViewMailTo (aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class VPUser implementation<br />
methods<br />
(VPUser.sina)
B.4. Group Mail System 137<br />
sendOriginatorReceiverViewMailTo (aUser : User)<br />
temps<br />
aMailMessage : OriginatorReceiverViewMail;<br />
sneakUser : User;<br />
begin<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a OriginatorReceiver Mail Message');<br />
aMailMessage.send;<br />
sneakUser.receive(aMailMessage)<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : VPUser;<br />
u2 : VPUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendOriginatorReceiverViewMailTo(u2);<br />
end<br />
B.4 Group Mail System<br />
class GroupMail interface<br />
externals<br />
GroupUser : Class;<br />
internals<br />
mail : OriginatorReceiverViewMail;<br />
conditions<br />
originatorView;<br />
input lters<br />
dis : Dispatch =f inner. , mail. g;<br />
end;<br />
class GroupMail implementation<br />
conditions<br />
originatorView<br />
temps<br />
orig : User;<br />
(OriginatorReceiverViewMailMain.sina)<br />
(GroupMail.sina)
138 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
begin<br />
orig mail.getMailOriginator;<br />
return (orig nil)<br />
jj (orig message.sender)<br />
jj ( orig.isKindOf(GroupUser)<br />
message.sender.isKindOf(GroupUser)<br />
orig.getGroup message.sender.getGroup )<br />
end<br />
end;<br />
class GroupUser interface<br />
internals<br />
user : VPUser;<br />
groupNumber : Integer;<br />
methods<br />
getGroup returns Integer;<br />
setGroup (num:Integer) returns nil;<br />
sendGroupMailTo(aUser : User) returns nil;<br />
input lters<br />
dis : Dispatch =f inner. , user. g;<br />
end;<br />
(GroupUser.sina)<br />
class GroupUser implementation<br />
initial<br />
begin<br />
groupNumber 0;<br />
end<br />
methods<br />
getGroup<br />
begin<br />
return groupNumber;<br />
end<br />
setGroup (num:Integer)<br />
begin<br />
groupNumber num;<br />
end<br />
sendGroupMailTo(aUser : User)<br />
temps<br />
aMailMessage : GroupMail;<br />
groupMember : GroupUser;<br />
begin<br />
groupMember.setName('GroupMember of MailOriginator');<br />
groupMember.setGroup(100);
B.5. Secure Mail System 139<br />
self.setGroup(100);<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a Group Mail Message');<br />
aMailMessage.send;<br />
groupMember.receive(aMailMessage);<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : GroupUser;<br />
u2 : GroupUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendGroupMailTo(u2);<br />
end<br />
B.5 Secure Mail System<br />
(GroupMailMain.sina)<br />
(SecureMail.sina)<br />
class SecureMail interface<br />
externals<br />
PGPUser : Class;<br />
internals<br />
mail : GroupMail;<br />
conditions<br />
pgpView;<br />
input lters<br />
dis : Dispatch =f pgpView->[getMailContents]getPGPMailContents,<br />
pgpView->[setMailContents]setPGPMailContents,<br />
inner. , mail. g;<br />
end;<br />
class SecureMail implementation<br />
conditions<br />
pgpView<br />
begin<br />
return message.sender.isKindOf(PGPUSer);<br />
end<br />
methods
140 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
getPGPMailContents returns String<br />
begin<br />
self.printLine('PGP decoding...');<br />
return self.getMailContents<br />
end;<br />
setPGPMailContents(s:String) returns nil<br />
begin<br />
self.printLine('PGP encoding...');<br />
self.setMailContents(s);<br />
end;<br />
end;<br />
class PGPUser interface<br />
internals<br />
user : GroupUser;<br />
publicKey : Integer;<br />
privateKey : Integer;<br />
methods<br />
setPGPPubKey(i:Integer) returns nil;<br />
getPGPPubKey returns Integer;<br />
setPGPPrivKey(i:Integer) returns nil;<br />
getPGPPrivKey returns Integer;<br />
sendSecureMailTo(aUser : User) returns nil;<br />
input lters<br />
dis : Dispatch =f inner. , user. g;<br />
end;<br />
class PGPUser implementation<br />
initial<br />
begin<br />
publicKey 0;<br />
privateKey 0;<br />
end<br />
methods<br />
setPGPPubKey(i:Integer)<br />
begin<br />
publicKey i;<br />
end<br />
getPGPPubKey<br />
begin<br />
return publicKey;<br />
end<br />
setPGPPrivKey(i:Integer)<br />
(PGPUser.sina)
B.6. Warning2 Mail System 141<br />
begin<br />
privateKey i;<br />
end<br />
getPGPPrivKey<br />
begin<br />
return privateKey;<br />
end<br />
sendSecureMailTo(aUser : User)<br />
temps<br />
aMailMessage : SecureMail;<br />
nonPGPUser : GroupUser;<br />
begin<br />
nonPGPUser.setName('Non PGP User');<br />
nonPGPUser.setGroup(100);<br />
self.setGroup(100);<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a Secure Mail Message');<br />
aMailMessage.send;<br />
nonPGPUser.receive(aMailMessage);<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : PGPUser;<br />
u2 : PGPUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendSecureMailTo(u2);<br />
end<br />
B.6 Warning2 Mail System<br />
class Warning2Mail interface<br />
internals<br />
mail : SecureMail;<br />
messageCounter : MCount;<br />
input lters<br />
(SecureMailMain.sina)<br />
(Warning2Mail.sina)
142 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
count : Meta = f<br />
[setMailContents,setMailOriginator,setMailReceiver,send]<br />
messageCounter.warning2Message g;<br />
dis : Dispatch =f inner. , mail. g;<br />
end;<br />
class Warning2Mail implementation<br />
comment<br />
No implementation, warning mechanism is h<strong>and</strong>led by the meta<br />
object.<br />
end;<br />
class Warning2User interface<br />
internals<br />
user : PGPUser;<br />
methods<br />
sendWarning2MailTo(aUser : User) returns nil;<br />
input lters<br />
dis : Dispatch =f inner. , user. g;<br />
end;<br />
class Warning2User implementation<br />
methods<br />
sendWarning2MailTo(aUser : User)<br />
temps<br />
aMailMessage : Warning2Mail;<br />
begin<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a Secure Mail Message');<br />
aMailMessage.setMailContents(<br />
'Contents of a Secure Mail Message');<br />
aMailMessage.send;<br />
end;<br />
end;<br />
class MCount interface<br />
internals<br />
counts : Dictionary;<br />
methods<br />
(Warning2User.sina)<br />
(MCount.sina)
B.7. Protected Mail System 143<br />
warning2Message(m:SinaMessage) returns nil;<br />
input lters<br />
dis : Dispatch =f inner. g;<br />
end;<br />
class MCount implementation<br />
methods<br />
warning2Message(m:SinaMessage)<br />
begin<br />
counts.atPut(m.selector,counts.atIfAbsent(m.selector,0) + 1);<br />
if (counts.at(m.selector) > 1)<br />
begin<br />
self.printLine('Warning, message sent more than once');<br />
end;<br />
m.continue;<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : Warning2User;<br />
u2 : Warning2User;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendWarning2MailTo(u2);<br />
end<br />
B.7 Protected Mail System<br />
class ProtectedMail interface<br />
internals<br />
mail : Warning2Mail;<br />
secdoc : SecureDocument;<br />
input lters<br />
err : Error = f securityClearance -> fgetMailContents,<br />
setMailContentsg,<br />
true ;fgetMailContents, setMailContentsg g;<br />
dis : Dispatch =f inner. , mail. , secdoc. g;<br />
end;<br />
class ProtectedMail implementation<br />
(Warning2MailMain.sina)<br />
(ProtectedMail.sina)
144 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong><br />
end;<br />
class ProtectedUser interface<br />
internals<br />
user : Warning2User;<br />
securityLevel : Integer;<br />
methods<br />
getSecurityLevel returns Integer;<br />
setSecurityLevel(i:Integer) returns nil;<br />
sendProtectedMailTo(aUser:User);<br />
inputFilters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class ProtectedUser implementation<br />
initial<br />
begin<br />
securityLevel 0;<br />
end;<br />
methods<br />
getSecurityLevel<br />
begin<br />
return securityLevel;<br />
end;<br />
setSecurityLevel(i:Integer)<br />
begin<br />
securityLevel i;<br />
end;<br />
sendProtectedMailTo(aUser : User)<br />
temps<br />
aMailMessage : ProtectedMail;<br />
begin<br />
aMailMessage.setMailOriginator(self);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setSecurityLevel(3);<br />
aMailMessage.setMailContents(<br />
'Contents of a Protected Mail Message');<br />
aMailMessage.send;<br />
aMailMessage.setSecurityLevel(1);<br />
aMailMessage.send;<br />
end;<br />
end;<br />
(ProtectedUser.sina)<br />
(ProtectedMailMain.sina)
B.7. Protected Mail System 145<br />
main<br />
temps<br />
u1 : PUser;<br />
u2 : PUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u1.setSecurityLevel(4);<br />
u2.setName('MailReceiver');<br />
u2.setSecurityLevel(2);<br />
u1.sendProtectedMailTo(u2);<br />
end
146 Appendix B. Sina Implementation of <strong>Multiple</strong> <strong>Views</strong>
Appendix C<br />
C ++ Implementation of <strong>Layering</strong><br />
C.1 Heading Mail System<br />
De nitions<br />
#ifndef HMAIL H<br />
#define HMAIL H<br />
#include "mail.hpp"<br />
class HUser : public User<br />
f<br />
public:<br />
virtual void receive(Mail );<br />
virtual void sendHeadingMailTo(HUser );<br />
g;<br />
class HeadingMail : public Mail<br />
f<br />
public:<br />
virtual char getMailHeading(void);<br />
virtual char getMailAsText(void);<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include <br />
#include <br />
#include <br />
#include "hmail.hpp"<br />
(hmail.hpp)<br />
(hmail.cc)<br />
147
148 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
void<br />
HUser::receive(Mail m)<br />
f<br />
char s ((HeadingMail )m)!getMailAsText();<br />
cout s "nn";<br />
delete s;<br />
g<br />
void<br />
HUser::sendHeadingMailTo(HUser u)<br />
f<br />
HeadingMail mailMessage new HeadingMail();<br />
mailMessage!setMailOriginator(this);<br />
mailMessage!setMailReceiver(u);<br />
mailMessage!setMailContents(<br />
"Contents of a Heading mail message");<br />
mailMessage!send();<br />
g<br />
char<br />
HeadingMail::getMailHeading(void)<br />
f<br />
char o, r, h, s;<br />
o this!getMailOriginator()!getName();<br />
r this!getMailReceiver()!getName();<br />
h this!getRoute()!getName();<br />
s (char )malloc(strlen(o)+strlen(r)+strlen(h)+31);<br />
sprintf(s,"Sender:ntnt%snnReceiver:nt%snnRoute:ntnt%snn",<br />
o,r,h);<br />
return s;<br />
g<br />
char<br />
HeadingMail::getMailAsText(void)<br />
f<br />
char c, h, r;<br />
c this!getMailContents();<br />
h this!getMailHeading();<br />
r (char )malloc(sizeof(char) (strlen(c)+strlen(h)+1));<br />
strcpy(r,h);<br />
strcat(r,c);<br />
delete h;<br />
return r;
C.2. Attachment Mail System 149<br />
g<br />
#define CALL TEST FUNCTION test heading mail();<br />
void test heading mail(void)<br />
f<br />
cout "Heading Mail testnn";<br />
HUser u1 new HUser();<br />
u1!setName("MailOriginator");<br />
HUser u2 new HUser();<br />
u2!setName("MailReceiver");<br />
u1!sendHeadingMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "mail.cc"<br />
C.2 Attachment Mail System<br />
De nitions<br />
#ifndef AMAIL H<br />
#define AMAIL H<br />
#include "hmail.hpp"<br />
class AUser : public HUser<br />
f<br />
public:<br />
virtual void sendAttachmentMailTo(AUser );<br />
g;<br />
class Attachment<br />
f<br />
public:<br />
Attachment() f lename NULL; g<br />
virtual char getFilename(void) f return lename; g<br />
virtual void setFilename(char s) f lename s; g<br />
private:<br />
char lename;<br />
g;<br />
class AttachmentMail : public HeadingMail<br />
(amail.hpp)
150 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
f<br />
public:<br />
AttachmentMail() f attachment NULL; g<br />
virtual Attachment getMailAttachment(void) f return attachment; g<br />
virtual void setMailAttachment(Attachment a) f attachment a; g<br />
virtual char getMailHeading(void);<br />
private:<br />
Attachment attachment;<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include <br />
#include <br />
#include <br />
#include "amail.hpp"<br />
void<br />
AUser::sendAttachmentMailTo(AUser u)<br />
f<br />
AttachmentMail aMailMessage new AttachmentMail();<br />
Attachment a new Attachment();<br />
a!setFilename(" /attachment.doc");<br />
aMailMessage!setMailOriginator(this);<br />
aMailMessage!setMailReceiver(u);<br />
aMailMessage!setMailContents(<br />
"Contents of an attachment mail message");<br />
aMailMessage!setMailAttachment(a);<br />
aMailMessage!send();<br />
g<br />
char<br />
AttachmentMail::getMailHeading(void)<br />
f<br />
char h, a, s;<br />
h HeadingMail::getMailHeading();<br />
if ( attachment NULL) f<br />
s h;<br />
g else f<br />
a this!getMailAttachment()!getFilename();<br />
(amail.cc)
C.3. ReadNoti cation Mail System 151<br />
g<br />
s (char )malloc(strlen(h)+strlen(a)+14);<br />
sprintf(s,"%sAttachment:nt%snn",h,a);<br />
delete h;<br />
g<br />
return s;<br />
#define CALL TEST FUNCTION test attachment mail();<br />
void test attachment mail(void)<br />
f<br />
cout "Attachment Mail testnn";<br />
AUser u1 new AUser();<br />
u1!setName("MailOriginator");<br />
AUser u2 new AUser();<br />
u2!setName("MailReceiver");<br />
u1!sendAttachmentMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "hmail.cc"<br />
C.3 ReadNoti cation Mail System<br />
De nitions<br />
#ifndef RNMAIL H<br />
#define RNMAIL H<br />
#include "usvmail.hpp"<br />
class RNUser : public MVUser<br />
f<br />
public:<br />
virtual void sendReadNoti cationMailTo(RNUser u);<br />
virtual char className(void) f return "RNUser"; g<br />
g;<br />
class ReadNoti cationMail : public UserSystemViewMail<br />
f<br />
public:<br />
ReadNoti cationMail() f mustNotify 0; noti ed 0; g<br />
virtual void setNotify(int i) f mustNotify i; g<br />
(rnmail.hpp)
152 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
virtual char getMailContents(Object );<br />
protected:<br />
virtual int senderIsReceiverAndMustNotify(Object sender);<br />
virtual int isUserView(Object sender);<br />
virtual void notify(void);<br />
virtual char className(void) f return "ReadNotificationMail"; g<br />
private:<br />
int mustNotify;<br />
int noti ed;<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
#include "rnmail.hpp"<br />
(rnmail.cc)<br />
void<br />
RNUser::sendReadNoti cationMailTo(RNUser u)<br />
f<br />
ReadNoti cationMail mailMessage new ReadNoti cationMail();<br />
mailMessage!setMailOriginator(this,this);<br />
mailMessage!setMailReceiver(this,u);<br />
mailMessage!setMailContents(this,<br />
"Contents of a read notification mail message");<br />
mailMessage!setNotify(1);<br />
mailMessage!send(this);<br />
g<br />
char<br />
ReadNoti cationMail::getMailContents(Object sender)<br />
f<br />
if (this!senderIsReceiverAndMustNotify(sender))<br />
this!notify();<br />
return UserSystemViewMail::getMailContents(sender);<br />
g<br />
int<br />
ReadNoti cationMail::senderIsReceiverAndMustNotify(Object sender)<br />
f<br />
return (this!getMailReceiver(this) sender)<br />
&& mustNotify
C.4. History Mail System 153<br />
g<br />
&& !noti ed;<br />
int<br />
ReadNoti cationMail::isUserView(Object sender)<br />
f<br />
return sender!isKindOf(UserSystemViewMailClass)<br />
jj UserSystemViewMail::isUserView(sender);<br />
g<br />
void<br />
ReadNoti cationMail::notify(void)<br />
f<br />
ReadNoti cationMail m new ReadNoti cationMail();<br />
noti ed 1;<br />
m!setMailOriginator(this,this!getMailReceiver(this));<br />
m!setMailReceiver(this,this!getMailOriginator(this));<br />
m!setMailContents(this,"Read Notification");<br />
m!setNotify(0);<br />
m!send(this);<br />
g<br />
#define CALL TEST FUNCTION test readnoti cation mail();<br />
void test readnoti cation mail(void)<br />
f<br />
cout "Read Notification Mail testnn";<br />
RNUser u1 new RNUser();<br />
u1!setName("MailOriginator");<br />
RNUser u2 new RNUser();<br />
u2!setName("MailReceiver");<br />
u1!sendReadNoti cationMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "usvmail.cc"<br />
C.4 History Mail System<br />
De nitions<br />
#ifndef HISMAIL H<br />
#define HISMAIL H<br />
(hismail.hpp)
154 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
#include "rnmail.hpp"<br />
class HisUser : public RNUser<br />
f<br />
public:<br />
virtual void sendHistoryMailTo(HisUser );<br />
virtual char className(void) f return "HisUser"; g<br />
g;<br />
class HistoryMail : public ReadNoti cationMail<br />
f<br />
public:<br />
HistoryMail() f initMeta(); g<br />
HistoryMail() f closeMeta(); g<br />
virtual void historyReport(void);<br />
virtual void setMailOriginator(Object ,MVUser );<br />
virtual MVUser getMailOriginator(Object );<br />
virtual void setMailReceiver(Object ,MVUser );<br />
virtual MVUser getMailReceiver(Object );<br />
virtual void setMailContents(Object ,char );<br />
virtual char getMailContents(Object );<br />
virtual void send(Object );<br />
virtual void reply(Object );<br />
virtual void approve(Object );<br />
virtual int isApproved(Object );<br />
virtual void setDelivered(Object );<br />
virtual int isDelivered(Object );<br />
virtual void setRoute(Object ,MVMailH<strong>and</strong>ler );<br />
virtual MVMailH<strong>and</strong>ler getRoute(Object );<br />
virtual char className(void) f return "HistoryMail"; g<br />
private:<br />
void initMeta(void) f report NULL; g<br />
void closeMeta(void) f if (report) delete report; g<br />
virtual void doMeta(char selector, Object sender);<br />
char report;<br />
g;<br />
#endif<br />
Implementation<br />
#include <br />
(hismail.cc)
C.4. History Mail System 155<br />
#include <br />
#include <br />
#include <br />
#include "hismail.hpp"<br />
#define MAX(A,B) (A
156 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
g<br />
size size = old info = +<br />
strlen(ts) = time info = +<br />
1 = tab = +<br />
MAX(strlen(cs),15) = for sender name = +<br />
1 = tab = +<br />
strlen(selector) +<br />
2 = NL + n0 = ;<br />
s (char )malloc(sizeof(char) size);<br />
sprintf(s,"%s%s %-15s %snn",report,ts,cs,selector);<br />
if (report[0] 6= 0)<br />
delete report;<br />
report s;<br />
void<br />
HistoryMail::setMailOriginator(Object sender,MVUser user)<br />
f<br />
this!doMeta("setMailOriginator",sender);<br />
ReadNoti cationMail::setMailOriginator(sender,user);<br />
g<br />
MVUser<br />
HistoryMail::getMailOriginator(Object sender)<br />
f<br />
this!doMeta("getMailOriginator",sender);<br />
return ReadNoti cationMail::getMailOriginator(sender);<br />
g<br />
void<br />
HistoryMail::setMailReceiver(Object sender,MVUser user)<br />
f<br />
this!doMeta("setMailReceiver",sender);<br />
ReadNoti cationMail::setMailReceiver(sender,user);<br />
g<br />
MVUser<br />
HistoryMail::getMailReceiver(Object sender)<br />
f<br />
this!doMeta("getMailReceiver",sender);<br />
return ReadNoti cationMail::getMailReceiver(sender);<br />
g<br />
void
C.4. History Mail System 157<br />
HistoryMail::setMailContents(Object sender,char s)<br />
f<br />
this!doMeta("setMailContents",sender);<br />
ReadNoti cationMail::setMailContents(sender,s);<br />
g<br />
char<br />
HistoryMail::getMailContents(Object sender)<br />
f<br />
this!doMeta("getMailContents",sender);<br />
return ReadNoti cationMail::getMailContents(sender);<br />
g<br />
void<br />
HistoryMail::send(Object sender)<br />
f<br />
this!doMeta("send",sender);<br />
ReadNoti cationMail::send(sender);<br />
g<br />
void<br />
HistoryMail::reply(Object sender)<br />
f<br />
this!doMeta("reply",sender);<br />
ReadNoti cationMail::reply(sender);<br />
g<br />
void<br />
HistoryMail::approve(Object sender)<br />
f<br />
this!doMeta("approve",sender);<br />
ReadNoti cationMail::approve(sender);<br />
g<br />
int<br />
HistoryMail::isApproved(Object sender)<br />
f<br />
this!doMeta("isApproved",sender);<br />
return ReadNoti cationMail::isApproved(sender);<br />
g<br />
void<br />
HistoryMail::setDelivered(Object sender)<br />
f
158 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
g<br />
this!doMeta("setDelivered",sender);<br />
ReadNoti cationMail::setDelivered(sender);<br />
int<br />
HistoryMail::isDelivered(Object sender)<br />
f<br />
this!doMeta("isDelivered",sender);<br />
return ReadNoti cationMail::isDelivered(sender);<br />
g<br />
void<br />
HistoryMail::setRoute(Object sender,MVMailH<strong>and</strong>ler h)<br />
f<br />
this!doMeta("setRoute",sender);<br />
ReadNoti cationMail::setRoute(sender,h);<br />
g<br />
MVMailH<strong>and</strong>ler<br />
HistoryMail::getRoute(Object sender)<br />
f<br />
this!doMeta("getRoute",sender);<br />
return ReadNoti cationMail::getRoute(sender);<br />
g<br />
#define CALL TEST FUNCTION test history mail();<br />
void test history mail(void)<br />
f<br />
cout "History Mail testnn";<br />
HisUser u1 new HisUser();<br />
u1!setName("MailOriginator");<br />
HisUser u2 new HisUser();<br />
u2!setName("MailReceiver");<br />
u1!sendHistoryMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "rnmail.cc"
C.5. Dynamic Mail System 159<br />
C.5 Dynamic Mail System<br />
De nitions<br />
#ifndef DMAIL H<br />
#define DMAIL H<br />
#include "usvmail.hpp"<br />
class MailComponent;<br />
class DynamicMail;<br />
class DUser : public MVUser<br />
f<br />
public:<br />
virtual void receive(MailComponent );<br />
virtual void sendDynamicMailTo(DUser );<br />
virtual char className(void) f return "DUser"; g<br />
g;<br />
class DMailH<strong>and</strong>ler : public MailH<strong>and</strong>ler, public Object<br />
f<br />
public:<br />
virtual int send(MailComponent );<br />
static DMailH<strong>and</strong>ler Instance(void);<br />
virtual char className(void) f return "DMailH<strong>and</strong>ler"; g<br />
protected:<br />
DMailH<strong>and</strong>ler() fg<br />
virtual DMailH<strong>and</strong>ler() fg<br />
static DMailH<strong>and</strong>ler instance;<br />
g;<br />
DMailH<strong>and</strong>ler DMailH<strong>and</strong>ler:: instance (DMailH<strong>and</strong>ler )0;<br />
(dmail.hpp)<br />
class MailComponent :public Object f<br />
public:<br />
virtual void setMailOriginator(MailComponent ,Object ,DUser ) 0;<br />
virtual DUser getMailOriginator(MailComponent ,Object ) 0;<br />
virtual void setMailReceiver(MailComponent ,Object ,DUser ) 0;<br />
virtual DUser getMailReceiver(MailComponent ,Object ) 0;<br />
virtual void setMailContents(MailComponent ,Object ,char ) 0;<br />
virtual char getMailContents(MailComponent ,Object ) 0;<br />
virtual void send(MailComponent ,Object ) 0;<br />
virtual void reply(MailComponent ,Object ) 0;<br />
virtual void approve(MailComponent ,Object ) 0;
160 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
g;<br />
virtual int isApproved(MailComponent ,Object ) 0;<br />
virtual void setDelivered(MailComponent ,Object ) 0;<br />
virtual int isDelivered(MailComponent ,Object ) 0;<br />
virtual void setRoute(MailComponent ,Object ,DMailH<strong>and</strong>ler ) 0;<br />
virtual DMailH<strong>and</strong>ler getRoute(MailComponent ,Object ) 0;<br />
virtual char className(void) f return "MailComponent"; g<br />
virtual void historyReport(void) fg;<br />
class DynamicMail : public MailComponent f<br />
public:<br />
DynamicMail();<br />
virtual DynamicMail();<br />
virtual void setMailOriginator(MailComponent ,Object ,DUser );<br />
virtual DUser getMailOriginator(MailComponent ,Object );<br />
virtual void setMailReceiver(MailComponent ,Object ,DUser );<br />
virtual DUser getMailReceiver(MailComponent ,Object );<br />
virtual void setMailContents(MailComponent ,Object ,char );<br />
virtual char getMailContents(MailComponent ,Object );<br />
virtual void send(MailComponent ,Object );<br />
virtual void reply(MailComponent ,Object );<br />
virtual void approve(MailComponent ,Object );<br />
virtual int isApproved(MailComponent ,Object );<br />
virtual void setDelivered(MailComponent ,Object );<br />
virtual int isDelivered(MailComponent ,Object );<br />
virtual void setRoute(MailComponent ,Object ,DMailH<strong>and</strong>ler );<br />
virtual DMailH<strong>and</strong>ler getRoute(MailComponent ,Object );<br />
virtual char className(void) f return "DynamicMail"; g<br />
private:<br />
Mail mail;<br />
g;<br />
class MailDecorator : public MailComponent f<br />
public:<br />
MailDecorator(MailComponent p) f component p; g<br />
virtual void setMailOriginator(MailComponent svr,Object o,DUser u)<br />
f<br />
component!setMailOriginator((svr?svr:this),o,u);<br />
g<br />
virtual DUser getMailOriginator(MailComponent svr,Object o) f<br />
return component!getMailOriginator((svr?svr:this),o);<br />
g<br />
virtual void setMailReceiver(MailComponent svr,Object o,DUser u) f<br />
component!setMailReceiver((svr?svr:this),o,u);
C.5. Dynamic Mail System 161<br />
f<br />
g<br />
virtual DUser getMailReceiver(MailComponent svr,Object o) f<br />
return component!getMailReceiver((svr?svr:this),o);<br />
g<br />
virtual void setMailContents(MailComponent svr,Object o,char s) f<br />
component!setMailContents((svr?svr:this),o,s);<br />
g<br />
virtual char getMailContents(MailComponent svr,Object o) f<br />
return component!getMailContents((svr?svr:this),o);<br />
g<br />
virtual void send(MailComponent svr,Object o) f<br />
component!send((svr?svr:this),o);<br />
g<br />
virtual void reply(MailComponent svr,Object o) f<br />
component!reply((svr?svr:this),o);<br />
g<br />
virtual void approve(MailComponent svr,Object o) f<br />
component!approve((svr?svr:this),o);<br />
g<br />
virtual int isApproved(MailComponent svr,Object o) f<br />
return component!isApproved((svr?svr:this),o);<br />
g<br />
virtual void setDelivered(MailComponent svr,Object o) f<br />
component!setDelivered((svr?svr:this),o);<br />
g<br />
virtual int isDelivered(MailComponent svr,Object o) f<br />
return component!isDelivered((svr?svr:this),o);<br />
g<br />
virtual void setRoute(MailComponent svr,Object o,DMailH<strong>and</strong>ler h)<br />
component!setRoute((svr?svr:this),o,h);<br />
g<br />
virtual DMailH<strong>and</strong>ler getRoute(MailComponent svr,Object o) f<br />
return component!getRoute((svr?svr:this),o);<br />
g<br />
virtual void historyReport(void) f<br />
component!historyReport();<br />
g<br />
virtual char className(void) f return "MailDecorator"; g<br />
private:<br />
MailComponent component;<br />
g;<br />
class MailReadNoti er : public MailDecorator f
162 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
public:<br />
MailReadNoti er(MailComponent d):MailDecorator(d) f noti ed 0; g<br />
virtual char getMailContents(MailComponent ,Object );<br />
virtual char className(void) f return "MailReadNotifier"; g<br />
protected:<br />
virtual int senderIsReceiverAndMustNotify(<br />
MailComponent ,Object sender);<br />
virtual void notify(MailComponent );<br />
private:<br />
int noti ed;<br />
g;<br />
class MailHistory : public MailDecorator f<br />
public:<br />
MailHistory(MailComponent d):MailDecorator(d) f initMeta(); g<br />
virtual MailHistory() f closeMeta(); g<br />
virtual void historyReport(void);<br />
virtual void setMailOriginator(MailComponent ,Object ,DUser );<br />
virtual DUser getMailOriginator(MailComponent ,Object );<br />
virtual void setMailReceiver(MailComponent ,Object ,DUser );<br />
virtual DUser getMailReceiver(MailComponent ,Object );<br />
virtual void setMailContents(MailComponent ,Object ,char );<br />
virtual char getMailContents(MailComponent ,Object );<br />
virtual void send(MailComponent ,Object );<br />
virtual void reply(MailComponent ,Object );<br />
virtual void approve(MailComponent ,Object );<br />
virtual int isApproved(MailComponent ,Object );<br />
virtual void setDelivered(MailComponent ,Object );<br />
virtual int isDelivered(MailComponent ,Object );<br />
virtual void setRoute(MailComponent ,Object ,DMailH<strong>and</strong>ler );<br />
virtual DMailH<strong>and</strong>ler getRoute(MailComponent ,Object );<br />
virtual char className(void) f return "MailHistory"; g<br />
private:<br />
virtual void initMeta(void) f report NULL; g<br />
virtual void closeMeta(void) f if (report) delete report; g<br />
virtual void doMeta(char selector, Object sender);<br />
char report;<br />
g;<br />
#endif<br />
Implementation<br />
(dmail.cc)
C.5. Dynamic Mail System 163<br />
#include <br />
#include <br />
#include <br />
#include <br />
#include <br />
#include "dmail.hpp"<br />
#define MAX(A,B) (A
164 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
g<br />
instance!setName("The Only DMailH<strong>and</strong>ler");<br />
g<br />
return (DMailH<strong>and</strong>ler ) instance;<br />
int<br />
DMailH<strong>and</strong>ler::send(MailComponent m)<br />
f<br />
if (m!getMailReceiver(0,this) 6= (DUser )0) f<br />
m!approve(0,this);<br />
g<br />
if (m!isApproved(0,this)) f<br />
m!setRoute(0,this,this);<br />
m!setDelivered(0,this);<br />
m!getMailReceiver(0,this)!receive(m);<br />
return 0;<br />
g else f<br />
return -1;<br />
g<br />
g<br />
DynamicMail::DynamicMail()<br />
f<br />
mail new Mail();<br />
assert( mail 6= (Mail )0);<br />
g<br />
DynamicMail:: DynamicMail()<br />
f<br />
delete mail;<br />
g<br />
void<br />
DynamicMail::setMailOriginator(MailComponent svr,<br />
Object sender,<br />
DUser u)<br />
f<br />
mail!setMailOriginator(u);<br />
g<br />
DUser<br />
DynamicMail::getMailOriginator(MailComponent svr,Object sender)<br />
f<br />
return (DUser ) mail!getMailOriginator();
C.5. Dynamic Mail System 165<br />
g<br />
void<br />
DynamicMail::setMailReceiver(MailComponent svr,<br />
Object sender,<br />
DUser u)<br />
f<br />
mail!setMailReceiver(u);<br />
g<br />
DUser<br />
DynamicMail::getMailReceiver(MailComponent svr,Object sender)<br />
f<br />
return (DUser ) mail!getMailReceiver();<br />
g<br />
void<br />
DynamicMail::setMailContents(MailComponent svr,Object sender,char s)<br />
f<br />
mail!setMailContents(s);<br />
g<br />
char<br />
DynamicMail::getMailContents(MailComponent svr,Object sender)<br />
f<br />
return mail!getMailContents();<br />
g<br />
void<br />
DynamicMail::send(MailComponent svr,Object sender)<br />
f<br />
DMailH<strong>and</strong>ler::Instance()!send((svr?svr:this));<br />
g<br />
void<br />
DynamicMail::reply(MailComponent svr,Object sender)<br />
f<br />
mail!reply();<br />
g<br />
void<br />
DynamicMail::approve(MailComponent svr,Object sender)<br />
f<br />
mail!approve();
166 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
g<br />
int<br />
DynamicMail::isApproved(MailComponent svr,Object sender)<br />
f<br />
return mail!isApproved();<br />
g<br />
void<br />
DynamicMail::setDelivered(MailComponent svr,Object sender)<br />
f<br />
mail!setDelivered();<br />
g<br />
int<br />
DynamicMail::isDelivered(MailComponent svr,Object sender)<br />
f<br />
return mail!isDelivered();<br />
g<br />
void<br />
DynamicMail::setRoute(MailComponent svr,<br />
Object sender,<br />
DMailH<strong>and</strong>ler mh)<br />
f<br />
mail!setRoute(mh);<br />
g<br />
DMailH<strong>and</strong>ler<br />
DynamicMail::getRoute(MailComponent svr,Object sender)<br />
f<br />
return (DMailH<strong>and</strong>ler ) mail!getRoute();<br />
g<br />
char<br />
MailReadNoti er::getMailContents(MailComponent svr,Object sender)<br />
f<br />
if (this!senderIsReceiverAndMustNotify(svr?svr:this,sender))<br />
this!notify(svr?svr:this);<br />
return MailDecorator::getMailContents(svr?svr:this,sender);<br />
g<br />
int<br />
MailReadNoti er::
C.5. Dynamic Mail System 167<br />
senderIsReceiverAndMustNotify(MailComponent svr,<br />
Object sender)<br />
f<br />
return (this!getMailReceiver(svr,this) sender) && !noti ed;<br />
g<br />
void<br />
MailReadNoti er::notify(MailComponent svr)<br />
f<br />
DynamicMail m new DynamicMail();<br />
noti ed 1;<br />
m!setMailOriginator(0,svr,svr!getMailReceiver(0,svr));<br />
m!setMailReceiver(0,svr,svr!getMailOriginator(0,svr));<br />
m!setMailContents(0,svr,"Read Notification");<br />
m!send(0,svr);<br />
g<br />
void<br />
MailHistory::historyReport(void)<br />
f<br />
if (report)<br />
cout report;<br />
else<br />
cout "No report information";<br />
g<br />
void<br />
MailHistory::doMeta(char selector,Object sender)<br />
f<br />
char s, ts, cs;<br />
int size;<br />
time tt;<br />
if (!report)<br />
report "";<br />
size strlen(report);<br />
t time(NULL);<br />
ts ctime(&t);<br />
ts[strlen(ts)-1] 0; = remove NL =<br />
cs sender!asString();<br />
size size = old info = +<br />
strlen(ts) = time info = +
168 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
g<br />
1 = tab = +<br />
MAX(strlen(cs),15) = for sender name = +<br />
1 = tab = +<br />
strlen(selector) +<br />
2 = NL + n0 = ;<br />
s (char )malloc(sizeof(char) size);<br />
sprintf(s,"%s%s %-15s %snn",report,ts,cs,selector);<br />
if (report[0] 6= 0)<br />
delete report;<br />
report s;<br />
void<br />
MailHistory::setMailOriginator(MailComponent svr,<br />
Object sender,<br />
DUser user)<br />
f<br />
this!doMeta("setMailOriginator",sender);<br />
MailDecorator::setMailOriginator(svr,sender,user);<br />
g<br />
DUser<br />
MailHistory::getMailOriginator(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("getMailOriginator",sender);<br />
return MailDecorator::getMailOriginator(svr,sender);<br />
g<br />
void<br />
MailHistory::setMailReceiver(MailComponent svr,<br />
Object sender,<br />
DUser user)<br />
f<br />
this!doMeta("setMailReceiver",sender);<br />
MailDecorator::setMailReceiver(svr,sender,user);<br />
g<br />
DUser<br />
MailHistory::getMailReceiver(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("getMailReceiver",sender);<br />
return MailDecorator::getMailReceiver(svr,sender);<br />
g
C.5. Dynamic Mail System 169<br />
void<br />
MailHistory::setMailContents(MailComponent svr,Object sender,char s)<br />
f<br />
this!doMeta("setMailContents",sender);<br />
MailDecorator::setMailContents(svr,sender,s);<br />
g<br />
char<br />
MailHistory::getMailContents(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("getMailContents",sender);<br />
return MailDecorator::getMailContents(svr,sender);<br />
g<br />
void<br />
MailHistory::send(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("send",sender);<br />
MailDecorator::send(svr,sender);<br />
g<br />
void<br />
MailHistory::reply(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("reply",sender);<br />
MailDecorator::reply(svr,sender);<br />
g<br />
void<br />
MailHistory::approve(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("approve",sender);<br />
MailDecorator::approve(svr,sender);<br />
g<br />
int<br />
MailHistory::isApproved(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("isApproved",sender);<br />
return MailDecorator::isApproved(svr,sender);<br />
g<br />
void
170 Appendix C. C ++ Implementation of <strong>Layering</strong><br />
MailHistory::setDelivered(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("setDelivered",sender);<br />
MailDecorator::setDelivered(svr,sender);<br />
g<br />
int<br />
MailHistory::isDelivered(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("isDelivered",sender);<br />
return MailDecorator::isDelivered(svr,sender);<br />
g<br />
void<br />
MailHistory::setRoute(MailComponent svr,Object sender,DMailH<strong>and</strong>ler h)<br />
f<br />
this!doMeta("setRoute",sender);<br />
MailDecorator::setRoute(svr,sender,h);<br />
g<br />
DMailH<strong>and</strong>ler<br />
MailHistory::getRoute(MailComponent svr,Object sender)<br />
f<br />
this!doMeta("getRoute",sender);<br />
return MailDecorator::getRoute(svr,sender);<br />
g<br />
#define CALL TEST FUNCTION test dynamic mail();<br />
void test dynamic mail(void)<br />
f<br />
cout "Dynamic Mail testnn";<br />
DUser u1 new DUser();<br />
u1!setName("MailOriginator");<br />
DUser u2 new DUser();<br />
u2!setName("MailReceiver");<br />
u1!sendDynamicMailTo(u2);<br />
g<br />
#include "main.inc"<br />
#include "usvmail.cc"
Appendix D<br />
Sina Implementation of <strong>Layering</strong><br />
D.1 Heading Mail System<br />
class HUser interface<br />
internals<br />
user : User;<br />
methods<br />
receive(aMail : Mail) returns nil;<br />
sendHeadingMailTo(aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class HUser implementation<br />
methods<br />
receive(aMail : Mail)<br />
begin<br />
server.printLine(aMail.getMailAsText);<br />
end;<br />
sendHeadingMailTo(aUser : User)<br />
temps<br />
aMailMessage : HeadingMail;<br />
begin<br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a Heading mail message');<br />
aMailMessage.send;<br />
end;<br />
end;<br />
#NoDefSyncFilter;<br />
(HUser.sina)<br />
(HeadingMail.sina)<br />
171
172 Appendix D. Sina Implementation of <strong>Layering</strong><br />
class HeadingMail interface<br />
internals<br />
mail : Mail;<br />
methods<br />
getMailHeading returns String;<br />
getMailAsText returns String;<br />
input lters<br />
disp : Dispatch =f inner. , mail. g;<br />
end;<br />
class HeadingMail implementation<br />
methods<br />
getMailHeading<br />
begin<br />
return 'Sender:<br />
'.copyAppend:(server.getMailOriginator.getName<br />
).copyAppend:('<br />
Receiver: '<br />
).copyAppend:(server.getMailReceiver.getName<br />
).copyAppend:('<br />
Route: '<br />
).copyAppend:(server.getRoute.getName);<br />
end;<br />
getMailAsText<br />
begin<br />
return server.getMailHeading.copyAppend:('<br />
').copyAppend:(server.getMailContents);<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : HUser;<br />
u2 : HUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendHeadingMailTo(u2);<br />
end<br />
D.2 Attachment Mail System<br />
(HeadingMailMain.sina)<br />
(Attachment.sina)
D.2. Attachment Mail System 173<br />
class Attachment interface<br />
methods<br />
setFilename(aName : String) returns nil;<br />
getFilename returns String;<br />
input lters<br />
disp : Dispatch =f inner. g;<br />
end;<br />
class Attachment implementation<br />
instvars<br />
lename : String;<br />
initial<br />
begin<br />
lename 'NoName';<br />
end;<br />
methods<br />
setFilename(aName : String)<br />
begin<br />
lename aName;<br />
end;<br />
getFilename<br />
begin<br />
return lename;<br />
end;<br />
end;<br />
class AUser interface<br />
internals<br />
user : HUser;<br />
methods<br />
sendAttachmentMailTo(aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class AUser implementation<br />
methods<br />
sendAttachmentMailTo(aUser : User)<br />
temps<br />
aMailMessage : AttachmentMail;<br />
attachment :Attachment;<br />
begin<br />
attachment.setFilename(' /attachment.doc');<br />
(AUser.sina)
174 Appendix D. Sina Implementation of <strong>Layering</strong><br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of an attachment mail message');<br />
aMailMessage.setMailAttachment(attachment);<br />
aMailMessage.send;<br />
end;<br />
end;<br />
(AttachmentMail.sina)<br />
class AttachmentMail interface<br />
internals<br />
mail : HeadingMail;<br />
conditions<br />
noAttachment;<br />
methods<br />
setMailAttachment(anAttachment :Attachment) returns nil;<br />
getMailAttachment returns Attachment;<br />
getMailHeading returns String;<br />
input lters<br />
skip : Dispatch =f<br />
noAttachment)[getMailHeading]mail.getMailHeading g;<br />
disp : Dispatch =f inner. , mail. g;<br />
end;<br />
class AttachmentMail implementation<br />
instvars<br />
attachment :Attachment;<br />
conditions<br />
noAttachment<br />
begin<br />
return attachment =nil;<br />
end;<br />
initial<br />
begin<br />
attachment nil;<br />
end;<br />
methods<br />
setMailAttachment(anAttachment :Attachment)<br />
begin<br />
attachment anAttachment;<br />
end;<br />
getMailAttachment<br />
begin
D.3. ReadNoti cation Mail System 175<br />
return attachment;<br />
end;<br />
getMailHeading<br />
begin<br />
return mail.getMailHeading.copyAppend:('<br />
Attachment: ').copyAppend:(server.getMailAttachment.getFilename);<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : AUser;<br />
u2 : AUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendAttachmentMailTo(u2);<br />
end<br />
D.3 ReadNoti cation Mail System<br />
class RNUser interface<br />
internals<br />
user : AUser;<br />
methods<br />
sendReadNoti cationMailTo(aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
(AttachmentMailMain.sina)<br />
(RNUser.sina)<br />
class RNUser implementation<br />
methods<br />
sendReadNoti cationMailTo(aUser : User)<br />
temps<br />
aMailMessage : ReadNoti cationMail;<br />
begin<br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a read notification mail message');<br />
aMailMessage.setNotify(true);<br />
aMailMessage.send;
176 Appendix D. Sina Implementation of <strong>Layering</strong><br />
end;<br />
end;<br />
class Noti er interface<br />
conditions<br />
done;<br />
methods<br />
setNotify(aBool : Boolean) returns nil;<br />
notify(aMessage : SinaMessage) returns nil;<br />
skipNotify(aMessage : SinaMessage) returns nil;<br />
input lters<br />
disp : Dispatch =f done)[notify]inner.skipNotify, inner. g;<br />
end;<br />
class Noti er implementation<br />
instvars<br />
mustNotify : Boolean;<br />
noti ed : Boolean;<br />
conditions<br />
done<br />
begin<br />
return (noti ed jj mustNotify.not);<br />
end;<br />
initial<br />
begin<br />
mustNotify false;<br />
noti ed false;<br />
end;<br />
methods<br />
skipNotify(aMessage : SinaMessage)<br />
begin<br />
aMessage.continue;<br />
end;<br />
setNotify(aBool : Boolean)<br />
begin<br />
mustNotify aBool;<br />
end;<br />
notify(aMessage : SinaMessage)<br />
temps<br />
aMailMessage : ReadNoti cationMail;<br />
begin<br />
noti ed true;<br />
aMessage.continue;<br />
(Noti er.sina)
D.3. ReadNoti cation Mail System 177<br />
aMailMessage.setMailOriginator(<br />
aMessage.receiver.getMailReceiver);<br />
aMailMessage.setMailReceiver(<br />
aMessage.receiver.getMailOriginator);<br />
aMailMessage.setMailContents('Read Notification');<br />
aMailMessage.setNotify(false);<br />
aMailMessage.send;<br />
end;<br />
end;<br />
(ReadNoti cationMail.sina)<br />
#NoDefSyncFilter;<br />
class ReadNoti cationMail interface<br />
internals<br />
mail : AttachmentMail;<br />
noti er : Noti er;<br />
conditions<br />
senderIsReceiver;<br />
input lters<br />
meta : Meta = f senderIsReceiver)[getMailContents]noti er.notify g;<br />
disp : Dispatch =f inner. , noti er.setNotify, mail. g;<br />
end;<br />
class ReadNoti cationMail implementation<br />
conditions<br />
senderIsReceiver<br />
begin<br />
return true; == mail.getMailReceiver = message.sender;<br />
== Compiler bug prevents correct evaluation of above<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : RNUser;<br />
u2 : RNUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendReadNoti cationMailTo(u2);<br />
end<br />
(ReadNoti cationMailMain.sina)
178 Appendix D. Sina Implementation of <strong>Layering</strong><br />
D.4 History Mail System<br />
class HisUser interface<br />
internals<br />
user : RNUser;<br />
methods<br />
sendHistoryMailTo(aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class HisUser implementation<br />
methods<br />
sendHistoryMailTo(aUser : User)<br />
temps<br />
aMailMessage : HistoryMail;<br />
begin<br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a history mail message');<br />
aMailMessage.send;<br />
aMailMessage.historyReport;<br />
end;<br />
end;<br />
class HistoryReporter interface<br />
externals<br />
Time : Class;<br />
methods<br />
saveHistory(aMessage : SinaMessage) returns nil;<br />
historyReport returns nil;<br />
input lters<br />
disp : Dispatch =f inner. g;<br />
end;<br />
class HistoryReporter implementation<br />
instvars<br />
report : String;<br />
initial<br />
begin<br />
report nil;<br />
end;<br />
(HisUser.sina)<br />
(HistoryReporter.sina)
D.4. History Mail System 179<br />
methods<br />
saveHistory(aMessage : SinaMessage)<br />
begin<br />
if report = nil<br />
then<br />
report '';<br />
end;<br />
report report.copyAppend:(Time.dateAndTimeNow.printString<br />
).copyAppend:(' '<br />
).copyAppend:(aMessage.sender.toString<br />
).copyAppend:(' '<br />
).copyAppend:(aMessage.selector).copyAppend:('<br />
');<br />
aMessage.continue;<br />
end;<br />
historyReport<br />
begin<br />
if report = nil<br />
then<br />
server.print('No report information');<br />
else<br />
server.print(report);<br />
end;<br />
end;<br />
end;<br />
class HistoryMail interface<br />
internals<br />
mail : ReadNoti cationMail;<br />
history : HistoryReporter;<br />
input lters<br />
meta : Meta = f [ ]history.saveHistory g;<br />
disp : Dispatch =f history.historyReport, mail. g;<br />
end;<br />
class HistoryMail implementation<br />
end;<br />
main<br />
temps<br />
u1 : HisUser;<br />
u2 : HisUser;<br />
begin<br />
(HistoryMail.sina)<br />
(HistoryMailMain.sina)
180 Appendix D. Sina Implementation of <strong>Layering</strong><br />
end<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendHistoryMailTo(u2);<br />
D.5 Dynamic Mail System<br />
class DUser interface<br />
internals<br />
user : User;<br />
methods<br />
sendDynamicMailTo(aUser : User) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , user. g;<br />
end;<br />
class DUser implementation<br />
methods<br />
sendDynamicMailTo(aUser : User)<br />
temps<br />
aMailMessage : DynamicMail;<br />
aHistory : HistoryProperty;<br />
aReadNot : MailReadNoti er;<br />
begin<br />
aMailMessage.addML(aReadNot);<br />
aMailMessage.addML(aHistory);<br />
aMailMessage.setMailOriginator(server);<br />
aMailMessage.setMailReceiver(aUser);<br />
aMailMessage.setMailContents(<br />
'Contents of a Dynamic Mail Message');<br />
aMailMessage.send;<br />
aMailMessage.historyReport;<br />
end;<br />
end;<br />
class BasicDL interface<br />
comment<br />
'This class provides the basic protocol for dynamic<br />
layering';<br />
internals<br />
ol : SinaObject; == For Object level layering<br />
ml : SinaObject; == For Meta level layering<br />
(DUser.sina)<br />
(BasicDL.sina)
D.5. Dynamic Mail System 181<br />
conditions<br />
isCascaded; == OL is lled<br />
isMeta; == ML is lled<br />
methods<br />
addOL(object : BasicDL) returns nil;<br />
addML(object : BasicDL) returns nil;<br />
process(aMessage : SinaMessage) returns nil;<br />
input lters<br />
== addML <strong>and</strong> addOL must be used in the top-level<br />
== because adding an object layer disables inner.<br />
d : Dispatch =f isMeta)[process]ml.process,<br />
true)f inner.addML, inner.addOL g,<br />
isCascaded)ol. ,<br />
isMeta)ml. ,<br />
true)inner.process g;<br />
end;<br />
class BasicDL implementation<br />
instvars<br />
cascaded : Boolean;<br />
meta : Boolean;<br />
conditions<br />
isCascaded<br />
begin<br />
return cascaded;<br />
end;<br />
isMeta<br />
begin<br />
return meta;<br />
end;<br />
initial<br />
begin<br />
cascaded false;<br />
meta false;<br />
end;<br />
methods<br />
addOL(object : BasicDL)<br />
begin<br />
if cascaded<br />
then<br />
object.addOL(ol);<br />
end;<br />
ol object;<br />
cascaded true;
182 Appendix D. Sina Implementation of <strong>Layering</strong><br />
end;<br />
addML(object : BasicDL)<br />
begin<br />
if meta<br />
then<br />
object.addOL(mop);<br />
end;<br />
ml object;<br />
meta true;<br />
end;<br />
process(aMessage : SinaMessage)<br />
begin<br />
aMessage.continue;<br />
end;<br />
end;<br />
class DynamicMail interface<br />
internals<br />
layers : BasicDL;<br />
mail : Mail;<br />
input lters<br />
meta : Meta = f [ ]layers.process g;<br />
dis : Dispatch =f layers. , mail. g;<br />
end;<br />
class DynamicMail implementation<br />
end;<br />
(DynamicMail.sina)<br />
(MailReadNoti er.sina)<br />
class MailReadNoti er interface<br />
internals<br />
basics : BasicDL;<br />
conditions<br />
notYetNoti ed;<br />
methods<br />
process (aMessage : SinaMessage) returns nil;<br />
input lters<br />
disp : Dispatch =f notYetNoti ed)inner. , true)basics. g;<br />
end;<br />
class MailReadNoti er implementation<br />
instvars<br />
noti ed : Boolean;
D.5. Dynamic Mail System 183<br />
conditions<br />
notYetNoti ed<br />
begin<br />
return !noti ed;<br />
end;<br />
initial<br />
begin<br />
noti ed false;<br />
end;<br />
methods<br />
process<br />
temps<br />
aMailMessage : DynamicMail;<br />
begin<br />
if aMessage.sender = aMessage.server.getMailReceiver<br />
&& aMessage.selector = 'getMailContents'<br />
then<br />
noti ed true;<br />
aMailMessage.setMailOriginator(<br />
aMessage.receiver.getMailReceiver);<br />
aMailMessage.setMailReceiver(<br />
aMessage.receiver.getMailOriginator);<br />
aMailMessage.setMailContents('Read Notification');<br />
aMailMessage.send;<br />
end<br />
basics.process(aMessage);<br />
end;<br />
end;<br />
(HistoryProperty.sina)<br />
class HistoryProperty interface<br />
internals<br />
basics : BasicDL;<br />
oldReporter : HistoryReporter;<br />
methods<br />
process(aMessage : SinaMessage) returns nil;<br />
input lters<br />
disp : Dispatch =f inner. , oldReporter.historyReport, basics. g;<br />
end;<br />
class HistoryProperty implementation<br />
instvars<br />
methods<br />
process(aMessage : SinaMessage)
184 Appendix D. Sina Implementation of <strong>Layering</strong><br />
begin<br />
oldReporter.saveHistory(aMessage);<br />
basics.process(aMessage);<br />
end;<br />
end;<br />
main<br />
temps<br />
u1 : DUser;<br />
u2 : DUser;<br />
begin<br />
u1.setName('MailOriginator');<br />
u2.setName('MailReceiver');<br />
u1.sendDynamicMailTo(u2);<br />
end<br />
(DynamicMailMain.sina)
Bibliography<br />
Aksit, M. <strong>and</strong> Bergmans, L.: 1992, Obstacles in object-oriented software development,<br />
in Paepcke (1992), pp. 341{358. ISSN 0362-1340, ISBN 0-201-<br />
53372-3.<br />
Aksit, M., Bergmans, L. <strong>and</strong> Vural, S.: 1992, An object-oriented languagedatabase<br />
integration model: The composition- lters approach, in Madsen<br />
(1992), pp. 372{395. ISBN 0-387-55668-0 / ISBN 3-540-55668-0.<br />
Aksit, M. <strong>and</strong> Bosch, J.: 1994, Issues in Object-Oriented Real-Time Language<br />
Design, in Halang <strong>and</strong> Stoyenko (1994), pp. 510{511. ISBN 3-540-57558-8,<br />
ISBN 0-387-57558-8, Proceedings of the NATO Advanced Study Institute<br />
on Real Time Computing, held in Sint Maarten, Dutch Antilles, October<br />
5{17, 1992.<br />
Aksit, M., Bosch, J., van der Sterren, W. <strong>and</strong> Bergmans, L.: 1994, Real-time<br />
speci cation inheritance anomalies <strong>and</strong> real-time lters, in Tokoro <strong>and</strong><br />
Pareschi (1994), pp. 386{407. ISBN 0-387-58202-9 / ISBN 3-540-58202-9.<br />
Aksit, M., Wakita, K., Bosch, J., Bergmans, L. <strong>and</strong> Yonezawa, A.: 1993, Abstracting<br />
object interactions using composition lters, in Guerraoui, Nierstrasz<br />
<strong>and</strong> Riveill (1993), pp. 152{184. ISBN 0-387-57932-X / ISBN 3-540-<br />
57932-X.<br />
Alex<strong>and</strong>er, C.: 1977, A Pattern Language, Oxford University Press.<br />
Algra, E.: 1994, Process programming <strong>and</strong> learning domains in object oriented<br />
hermeneutic software development, M.Sc. thesis, University of Twente,<br />
Dept. of Computer Science, P.O. box 217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Describes a framework <strong>and</strong> its specialisation for the HOOSD tool.<br />
Bergmans, L.: 1994, Composing Concurrent <strong>Objects</strong>, Ph.D. dissertation, University<br />
of Twente, Dept. of Computer Science, P.O. box 217, 7500 AE,<br />
Enschede, The Netherl<strong>and</strong>s. ISBN 90-9007359-0.<br />
Black, U. D.: 1991, OSI: a Model for Computer Communications St<strong>and</strong>ards,<br />
Prentice Hall. ISBN 0-13-637133-7.<br />
Bosch, J.: 1995, Language support for design patterns.<br />
*http://www.pt.hk-r.se/~bosch/despat.ps.Z<br />
Buschmann, F., Meunier, R., Rohnert, H., Sommerlad, P. <strong>and</strong> Stal, M.: 1996,<br />
Pattern-Oriented Software Architecture | A System of Patterns, John<br />
Wiley & Sons Ltd., Ba ns Lane, Chichester, West Sussex PO19 1UD,<br />
Engl<strong>and</strong>. ISBN 0-471-95869-7.<br />
185
186 Bibliography<br />
Ellis, M. A. <strong>and</strong> Stroustrup, B.: 1990, The Annotated C++ Reference Manual,<br />
Addison-Wesley Publishing Company, Reading, Massachusetts. ISBN 0-<br />
201-51459-1.<br />
Eur: 1997, Proceedings of the ECOOP '97, number 1241 in Lecture Notes in<br />
Computer Science, Springer-Verlag, Berlin Heidelberg.<br />
Ferber, J.: 1989, Computational re ection in class based object oriented languages,<br />
in Meyrowitz (1989), pp. 317{326. ISBN 0-0201-52249-7, ISSN<br />
0362-1340.<br />
Florijn, G., Meijers, M. <strong>and</strong> van Winsen, P.: 1997, Tool support for object<br />
oriented patterns, in Proceedings of the ECOOP '97 (Eur 1997), pp. 472{<br />
495.<br />
Gamma, E., Helm, R., Johnson, R. <strong>and</strong> Vlissides, J.: 1995, Design Patterns:<br />
Elements of Reusable Object-Oriented Software, Professional computing<br />
series, Addison-Wesley, Reading, MA. ISBN 0-201-63361-2.<br />
Gl<strong>and</strong>rup, M.: 1995, Extending c++ using the concepts of composition lters,<br />
M.Sc. thesis, University ofTwente, Dept. of Computer Science, P.O. box<br />
217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Guerraoui, R., Nierstrasz, O. <strong>and</strong> Riveill, M. (eds): 1993, ECOOP '93, Workshop<br />
on Object-Based Distributed Programming, number 791 in Lecture<br />
Notes in Computer Science, European Conference on Object-Oriented<br />
Programming, Springer-Verlag, Berlin Heidelberg. ISBN 0-387-57932-X<br />
/ ISBN 3-540-57932-X.<br />
Halang, W. A. <strong>and</strong> Stoyenko, A. D. (eds): 1994, Real Time Computing, Vol. 127<br />
of NATO ASI Series F: Computer <strong>and</strong> System Sciences, NATO Advanced<br />
Science Institutes, Springer-Verlag, Berlin, Heidelberg, New York. ISBN<br />
3-540-57558-8, ISBN 0-387-57558-8, Proceedings of the NATO Advanced<br />
Study Institute on Real Time Computing, held in Sint Maarten, Dutch<br />
Antilles, October 5{17, 1992.<br />
Helm, R., Holl<strong>and</strong>, I. M. <strong>and</strong> Gangopadhyay, D.: 1990, Contracts: Specifying<br />
behavioural compositions in object-oriented systems, Proceedings OOP-<br />
SLA/ECOOP '90, ACM SIGPLAN Notices, pp. 169{180. Published as<br />
Proceedings OOPSLA/ECOOP '90, ACM SIGPLAN Notices, volume 25,<br />
number 10.<br />
Johnson, R. E. <strong>and</strong> Foote, B.: 1988, Designing reusable classes, Journal of<br />
Object-Oriented Programming pp. 22{35.<br />
Koehorst, H.: 1994, De ning artifacts of prepatory work in hermeneutic objectoriented<br />
software development, M.Sc. thesis, University of Twente, Dept.<br />
of Computer Science, P.O. box 217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Describes an aspect of the HOOSD tool.<br />
Koopmans, P.: 1996, Sina/st | User's Guide <strong>and</strong> Reference Manual for Sina<br />
version 3.1, University of Twente, Dept. of Computer Science, P.O. box<br />
217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Lieberherr, K. J. <strong>and</strong> Holl<strong>and</strong>, I. M.: 1989, Assuring good style for objectoriented<br />
programs, IEEE Software pp. 38{48.
Bibliography 187<br />
Lieberman, H.: 1986, Using prototypical objects to implement shared behavior<br />
in object oriented systems, in Meyrowitz (1986), pp. 214{223. ISBN 0-<br />
89791-204-7.<br />
Madsen, O. L. (ed.): 1992, ECOOP '92, European Conference on Object-<br />
Oriented Programming, number 615 in Lecture Notes in Computer Science,<br />
European Conference on Object-Oriented Programming, Springer-Verlag,<br />
Berlin Heidelberg. ISBN 0-387-55668-0 / ISBN 3-540-55668-0.<br />
Meyrowitz, N. (ed.): 1986, OOPSLA '86 Conference Proceedings, Vol. 21 of<br />
SIGPLAN Notices, Association for Computing Machinery's Special Interest<br />
Group on Programming Languages (ACM/SIGPLAN), Association for<br />
Computing Machinery, Inc., 11 West 42nd Street, New York, New York<br />
10036, USA. ISBN 0-89791-204-7.<br />
Meyrowitz, N. (ed.): 1989, OOPSLA '89, Conference Proceedings, Vol. 24 of<br />
SIGPLAN Notices, Special Interest Group on Programming Languages,<br />
Association for Computing Machinery, Association for Computing Machinery,<br />
Inc., 11 West 42nd Street, New York, NY 10036, USA. ISBN<br />
0-0201-52249-7, ISSN 0362-1340.<br />
Minsky, N.H.<strong>and</strong>Pal, P.: 1995, Providing multiple views for objects by means<br />
of surrogates, Technical report, Rutgers University, New Brunswick, NJ<br />
08903 USA.<br />
*http://www.cs.rutgers.edu/~minsky/papers/surrogates-paper.ps<br />
Mordhorst, J. <strong>and</strong> van Dijk, W.: 1996, Composition lters in smalltalk, M.Sc.<br />
thesis, University of Twente, Dept. of Computer Science, P.O. box 217,<br />
7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Paepcke, A. (ed.): 1992, OOPSLA '92, Conference Proceedings, Vol. 27 of ACM<br />
SIGPLAN Notices, Association for Computing Machinery's Special Interest<br />
Group on Programming Languages (ACM/SIGPLAN), Association for<br />
Computing Machinery, Inc., 151 Broadway, New York, NY 10036. ISSN<br />
0362-1340, ISBN 0-201-53372-3.<br />
Pree, W.: 1994, Design Patterns for Object-Oriented Software Development,<br />
ACM Press Books, Addison-Wesley, Reading, MA. ISBN 0-201-42294-8.<br />
Schmidt, R. W.: n.d., Dynamically extensible objects in a class-based language.<br />
Stuurman, C.: 1996, Techniques for de ning composition lters using message<br />
manipulators, M.Sc. thesis, University ofTwente, Dept. of Computer Science,<br />
P.O. box 217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Tekinerdogan, B.: 1994, The design of an object-oriented framework for atomic<br />
transactions, M.Sc. thesis, University of Twente, Dept. of Computer Science,<br />
P.O. box 217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Tokoro, M. <strong>and</strong> Pareschi, R. (eds): 1994, ECOOP '94, Object-Oriented Programming,<br />
number 821 in Lecture Notes in Computer Science, European<br />
Conference on Object-Oriented Programming, Springer-Verlag, Berlin Heidelberg.<br />
ISBN 0-387-58202-9 / ISBN 3-540-58202-9.
188 Bibliography<br />
Vuijst, C.: 1994, Design of an object oriented framework for image algebra,<br />
M.Sc. thesis, University ofTwente, Dept. of Computer Science, P.O. box<br />
217, 7500 AE, Enschede, The Netherl<strong>and</strong>s.<br />
Wieringa, R. <strong>and</strong> Jonge, W. d.: 1991a, The identi cation of objects <strong>and</strong><br />
roles, Technical Report IR-267, Faculty of Mathematics <strong>and</strong> Computer<br />
Science, Vrije Universiteit, Amsterdam. Available for ftp in le 91-<br />
<strong>Objects</strong>Roles.ps.Z.<br />
Wieringa, R. <strong>and</strong> Jonge, W. d.: 1991b, The identi cation of objects <strong>and</strong> roles<br />
{ object identi ers revisited, Technical Report IR-267, Faculty of Mathematics<br />
<strong>and</strong> Computer Science, Vrije Universiteit, Amsterdam. Abbreviated<br />
<strong>and</strong> revised version of 91-<strong>Objects</strong>Roles.ps.Z. Available for ftp in le<br />
92-<strong>Objects</strong>Roles.ps.Z..