• Aucun résultat trouvé

3.3 Analyse et choix de conception

3.3.1 Propriétés du système réifiées par le contrat

Comme nous l’avons vu précédemment, la propriété de validité d’un assemblage se déduit de ses propriétés de conformité, compatibilité et responsabilité. Nous étudierons donc l’expression et la mise en oeuvre de chacune de ces dernières. Il faut noter que le contrat doit produire une expression de ces propriétés mais aussi faire appel aux outils convenables pour obtenir leur évaluation, afin d’en déduire l’évaluation de la validité de l’assemblage.

3.3.1.1 Conformité Définition

Nous définissons la conformité comme une propriété d’un élément du système contraint par rapport à sa spécification. Il y a conformité entre un élément de l’architecture et sa spécification, si la réalisation concrète (exécutable) du premier satisfait bien à la seconde. Nous considérerons la spécification comme une con-trainte qui peut être ou ne pas être satisfaite par la réalisation concrète de l’élé-ment.

Une forme d’évaluation de la conformité

Les éléments de système que nous envisageons étant des composants ou des ser-vices, leurs spécifications sont communément "boites noires" même si certains travaux sont en faveur de boites grises. Ainsi notre connaissance de ces éléments se limite à leurs échanges avec leur environnement et aux spécifications qui contraignent ces derniers. Il est donc intéressant de noter que ces échanges peuvent avoir lieu à dif-férents stades du cycle de vie des éléments. Durant la phase de configuration architec-turale, des éléments fournis peuvent par exemple être mis en relation avec d’autres requis, tandis que durant la phase d’exécution, données produites et requises sont échangées. Par ailleurs l’évaluation de la conformité d’une spécification est effectuée à l’aide d’un outil qui est associé à son formalisme et qui prend en entrée les obser-vations des échanges. Nous pouvons constater qu’il y a essentiellement trois objets d’observation sur lesquels évaluer la conformité d’un élément à sa spécification :

• observation de grandeurs d’exécution : sans observer la réalisation d’un élément il est possible d’observer ce que son exécution expose à son environnement, c’est à dire les données qu’il expose ou émet au cours de celle-ci (par exemple les paramètres d’une méthode pour l’évaluation de simples assertions),

• observation de paramètres de configuration : un élément d’architecture peut ex-poser des paramètres modifiables seulement durant sa phase de configuration

et qui peuvent être l’objet de l’observation (ces paramètres peuvent par exemple être utilisés dans une assertion en CCLJ),

• observation de la configuration architecturale : il s’agit d’observer à la fois les propriétés architecturales des éléments définies au moment de leur conception, et les relations établies entre eux au moment de la construction (ou reconfigura-tion) du système contraint (par exemple le nombre d’éléments connectés à une interface donnée peut être limité),

Dans notre exemple, si nous considérons la spécification suivante du<CruiseCtrl>:

(?sns.on; !csp.setThrottle*; ?sns.off)*

La vérification de la conformité du <CruiseCtrl>reposera sur l’observation des ap-pels émis ou reçues sur les méthodeson() off()etsetThrottle(). En effet ces obser-vations serviront d’entrées à un "runtimechecker" initialisé avec la spécification à véri-fier.

Réification de la conformité

La réification de la conformité d’un élément d’architecture à sa spécification consiste à expliciter différents points :

• l’élément d’architecture dont la spécification est considérée, et qui va être l’objet d’observation,

• l’expression de la contrainte contenue dans la spécification,

• les observations nécessaires à l’évaluation de la contrainte : elles seront déduites de l’expression de la contrainte et de l’outil d’évaluation associé au formalisme de celle-ci,

Problématique de l’observation

Il se pose alors le problème complexe de la définition et de la mise en oeuvre de l’observation d’un système. Il faut dans un premier temps parvenir à décrire ce qu’on veut observer et quand on souhaite l’observer. Notre objectif n’est pas de produire une taxonomie de ce qu’il est possible d’observer sur un système et à quels moments il est possible de faire des observations, mais de définir une approche pragmatique utile à la vérification des contraintes des spécifications. Nous procéderons donc en faisant ressortir des invariants dans les objets et moments d’observation :

• élément d’architecture attaché : la nature de la grandeur à observer change avec celle de la spécification (QoS, comportement, etc...), toutefois de par la nature des spécifications que nous retenons, les grandeurs sont toujours définies par rapport à un élément donné de l’architecture. En effet les spécifications sont par hypothèse modulaires, aussi ce qu’elles contraignent se définit obligatoirement par rapport à l’élément auquel elles sont associées. Ainsi quelque soit la nature de l’observation (temps de réponse, paramètre, configuration etc...), un constitu-ant architectural de cet élément (interfaces, méthodes etc...) devra être mentionné dans la description de l’observation pour faire le lien avec le système observé,

• déclencheur : que l’observation soit discrète ou continue, la grandeur qu’elle re-tourne doit être arrêtée à un instant donné, ainsi elle peut être définie par un ou plusieurs événements. Toutefois il faut noter que ces événements peuvent être originaires du système contraint ou de son environnement. Il peut aussi bien s’a-gir d’une interception de l’exécution que d’un timer externe qui se déclenche, voire de la réalisation d’une condition portant à la fois sur l’intérieur et l’environ-nement du système. D’une manière plus générale l’observation doit disposer de déclencheurs sensibles à ces différentes sortes d’événements et conditions. Dans le cas ou les événements sont originaires du système, ils doivent se déduire à nouveau de l’élément auquel est associé la spécification pour des raisons de mod-ularité.

En dehors de ces points, la part variable de la description des observations ne peut être modélisée par un système général de contrat car elle est propre à un formalisme ou une architecture donnée.

3.3.1.2 Compatibilité

Dans notre approche la compatibilité a pour objet d’exprimer que les échanges entre éléments de l’architecture se déroulent correctement, c’est à dire que les attentes des uns sont satisfaites par ce que fournissent les autres.

Définition

Deux, ou plus, entités sont compatibles si : toute grandeur émise par l’une est acceptable par celle(s) qui la reçoive(nt). Du point de vue des spécifications, cela revient à dire que toute grandeur émise qui satisfait à la spécification de l’émetteur, doit satisfaire à la (aux) spécification(s) du(es) récepteur(s).

Cette définition est une forme adaptée de celle que nous avons donné à la fin de l’in-troduction, soit :

la non-contradiction de spécifications qui, attachées à des entités dis-tinctes, contraignent des grandeurs communes

Elle a pour objet de ramener la notion de compatibilité aux échanges entre les éléments du système. En effet, la définition de compatibilité que nous avons donné initialement couvrait toutes les sortes de partage de grandeurs entre différents éléments du système et pas seulement les échanges.

Une forme d’évaluation de la compatibilité

Comme nous l’avons vu dans le paragraphe précédent, les spécifications modulaires contraignent ce que les éléments d’architecture s’échangent d’un point de vue local à chacun, aussi leur comparaison devrait donc permettre de prévoir si elles sont com-patibles. Suivant les formalismes l’expression de la compatibilité de deux ou plusieurs spécifications peut prendre différentes formes qui peuvent être évaluées de différentes manières. Dans notre exemple, si nous considérons les spécifications du comportement

des composants<Engine>et<CruiseCtrl>, ces deux composants seront compatibles si l’expression :

((?csp.setT hrottle; !f dk.notif yAction) ∗ ⊓(?sns.on; !csp.setT hrottle∗; ?sns.of f )∗) interprétée sous la forme évaluable suivante :

parallelCheck ((?csp.setThrottle; !fdk.notifyAction)*, // <Engine> (?sns.on; !csp.setThrottle*; ?sns.off)*) // <CruiseCtrl>

dans laquelleparallelCheckdénote la vérification par model checking de la composi-tion parallèle des spécificacomposi-tions, est évaluée à vrai.<CruiseCtrl>envoie des messages

setThrottleà<Engine>. L’évaluation vérifie que chaque fois que le message est émis il est bien attendu. Si chaque fois que le message est émis il est attendu, alors chaque fois que la spécification de<CruiseCtrl>est vraie (pour le messagesetThrottle) la spécification de<Engine>l’est aussi, et alors les deux spécifications sont compatibles. Si nous considérons maintenant les spécifications en CCLJ, S3 et S4 (cf 3.2.2.1), l’inter-prétation en CCLJ de leur compatibilité est la suivante :

On <Engine>

context float csp.getRTime (float throttle) post : (retour<5) => (retour < 10)

La valeurretour, retour de la méthodegetRTime, est la grandeur échangée entre les composants. Elle exprime que les composants sont compatibles si pour chaque retour de la méthodegetRTime, la post condition du client (récepteur de la grandeur)retour < 10est vraie tant que la post condition du serveur (émetteur de la grandeur)retour < 5l’est. L’évaluation de cet exemple est triviale et ne requiert pas d’observation de la grandeur échangée, mais ce n’est pas le cas général.

Nous pouvons donc voir que les observations nécessaires à l’évaluation de l’expression de compatibilité différeront suivant l’expression (cf l’exemple), le formalisme et l’outil d’évaluation disponible. Par exemple, la compatibilité de spécifications comportemen-tales en Behavior Protocol pourra être évaluée à l’aide d’un modelchecker, donc sans observation de l’exécution, tandis que celle de pré et post conditions de CCLJ le sera en observant les valeurs des paramètres et valeurs de retour fournis par l’exécution du système.

Réification

A nouveau, il ne s’agit pas pour nous d’établir une taxonomie de toutes les formes de compatibilité que le contrat devra prendre en compte mais d’identifier ce qu’elles ont en commun. C’est cette partie commune qui devra être modélisée dans le contrat car indépendante du formalisme et de l’architecture contrainte.

Ainsi ce qui est commun aux différentes expressions de compatibilité est qu’elles re-flètent les relations contenues dans l’architecture contrainte par le contrat. En effet les échanges entre éléments de l’architecture sont définis par les relations entre ceux-ci.

Toute grandeur exposée ou émise par un élément et consommée ou requise par un autre l’est via une relation établie entre ces deux derniers. Il convient donc pour chaque relation d’explorer les spécifications de ses extrêmités pour former l’expression expri-mant que chaque spécification contraignant une grandeur échangée d’un côté de la relation est compatible avec celle(s) contraignant cette même grandeur de l’autre côté de la relation. De ce fait, il faut noter qu’une expression de compatibilité, établie pour un ensemble d’éléments d’architecture, peut ne concerner qu’un sous ensemble des re-lations les unissant, et/ou un sous ensemble de leurs spécifications. Ainsi toute expres-sion de compatibilité ne vaut que si elle accompagnée des hypothèses qui décrivent sa portée aussi bien en termes de relations architecturales que de spécifications. Le contrat devra donc expliciter :

• l’expression de la compatibilité à évaluer ,

• l’ensemble des relations dont l’expression de la compatibilité garantit la validité, • les observations éventuellement nécessaires à l’évaluation,

• l’ensemble des spécifications prises en compte pour établir l’expression de la compatibilité

3.3.1.3 Responsabilité Définition

Nous définissons la responsabilité comme une propriété qui lie une entité (logi-cielle ou non) au résultat de l’évaluation de sa conformité à sa spécification. La sémantique de cette propriété est que l’entité responsable est celle à blamer en cas de non-satisfaction de la spécification, c’est à dire celle qui est considérée comme à l’origine de la non-satisfaction. Toutefois, pour être déclarée responsable, une entité doit être causalement liée au résultat de l’évaluation de la spécification, en effet l’objectif de cette propriété est de guider les actions de rétablissement de la conformité.

Sémantique

Dans le cadre de cette définition, nous pouvons distinguer deux grandes approches de la responsabilité suivant la nature de la cause :

• le responsable est à l’origine du résultat de l’évaluation : une modification du responsable entrainera alors une modification du résultat de l’évaluation. Dans cette approche, les composants ou services contraints sont les responsables de leur conformité à leurs spécifications, puisqu’ils sont à l’origine directe des ob-servations qui sont utilisées pour l’évaluation de la conformité. Modifier un com-posant ou un service modifiera le résultat de l’évaluation à la conformité. Cette approche privilégie une causalité directe entre les paramètres et le résultat de l’é-valuation. Par exemple, une méthode peut être considérée comme responsable du résultat de l’évaluation d’une post-condition sur sa valeur de retour,

• le responsable est celui dont l’action peut changer le résultat de l’évaluation : dans ce cadre sont considérées les entités capables d’influer sur l’origine du ré-sultat. Cette approche considère comme responsables non plus les composants ou les services, mais leurs développeurs, ou les assembleurs de l’application qui les ont choisi. Une causalité indirecte est dans ce cas considérée, puisque ce n’est plus l’origine (composant, service) des paramètres de l’évaluation qui est la cause, mais ce qui a produit cette origine (développeur, assembleur, etc...).

Nous considérerons la responsabilité associée à la cause directe du résultat de l’éval-uation, c’est à dire les composants et services comme responsables. En effet si nous considérions une causalité indirecte, c’est à dire par exemple les développeurs comme responsables, ce n’est plus les échanges entre composants qu’il faudrait étudier mais ceux entre les développeurs. Un développeur ne garantit pas la conformité de son com-posant à un autre comcom-posant avec lequel le sien interagit, il garantit la conformité à un autre développeur producteur du composant qui interagit avec le sien. Or cette garantie peut alors se teinter de considérations complètement externes à la nature de l’échange entre les composants, comme des considérations commerciales etc...

Une forme d’évaluation de la responsabilité

Si nous considérons la spécification d’un élément d’architecture, celle-ci est éval-uée sur la base d’un ensemble d’observations. Nous avons considéré jusqu’ici que ces observations mentionnaient explicitement les éléments ou parties d’éléments d’archi-tectures desquels elles étaient issues. Ainsi il est possible de distinguer les observations qui portent sur ce qu’un élément d’architecture expose, émet ou fournit de celles sur ce qu’il reçoit, consomme ou requiert. Or un élément d’architecture, ne peut en temps que cause, n’être responsable que des spécifications qui portent sur ce qu’il expose, émet ou fournit. Il est donc nécessaire d’interpréter les spécifications, par rapport à leur élé-ment porteur, pour en distinguer la garantie ou l’obligation, c’est à dire la partie dont le porteur est responsable.

Réification

Comme nous l’avons vu, la définition de la responsabilité relève de l’interprétation de la spécification pour en extraire une garantie telle que définie au paragraphe précé-dent. Nous pouvons remarquer que dans le cadre de l’approche hypothèse-garantie la spécification fait bien apparaître une garantie telle que nous la souhaitons. Mais elle fait aussi apparaître une hypothèse qui a alors pour objet de contraindre ce que le porteur de la spécification consomme, requiert ou reçoit de son environnement. Dans la séman-tique hypothèse-garantie, la satisfaction de l’hypothèse conditionne la responsabilité de son porteur vis à vis de la garantie contraignant alors ce qu’il fournit ou produit. Or cette sémantique est tout à fait celle que nous avons utilisé pour définir la validité d’un assemblage, dans les termes de l’échange, utilisés dans la conformité et la compatibil-ité, et dans ceux de l’engagement, utilisés dans la responsabilité : chaque participant s’engageant à fournir ce que ses pairs attendent pourvu que ceux-ci lui fournissent ce dont il a besoin. L’approche hypothèse-garantie représente donc le modèle dans lequel il faudra interpréter les spécifications pour les faire entrer dans le contrat tel que nous l’avons défini. Conformité, compatibilité, responsabilité vis à vis de spécifications

hypothèse-garantie, permettent d’exprimer la validité de l’assemblage telle que nous le souhaitons.