Rubriques

Explication Haut de la page

Les automates à états sont utilisés pour modéliser le comportement dynamique d'un élément de modèle, et plus particulièrement, les aspects événementiels du comportement du système (voir Concepts : Evénements et signaux). Les automates à états sont particulièrement utilisés pour définir le comportement dépendant des états, ou le comportement variant selon l'état dans lequel se trouve l'élément de modèle. Les éléments de modèle dont le comportement ne varie pas selon leur état n'ont pas besoin que les automates à états décrivent leur comportement (ces éléments sont généralement des classes passives qui ont pour principale responsabilité la gestion des données). Les automates à états doivent être utilisés en particulier pour modéliser le comportement de classes actives qui utilisent les événements d'appel et de signal pour implémenter leurs opérations (comme des transitions dans l'automate à états de la classe).

Un automate à états consiste d'états, liés par des transitions. Un état est une condition d'un objet dans laquelle il effectue une activité ou attend un événement. Une transition est une relation entre deux états déclenchée par un événement donné, qui exécute certaines actions ou évaluations, et qui entraîne un état final spécifique. Les éléments de l'automate à états sont décrits dans la Figure 1.

Diagramme montrant la notation de l'automate à états.

Figure 1. Notation d'automate à états.

Un simple programme d'édition peut être vu comme un automate à états fini possédant les états Vide, En attente de commande, et En attente de texte. Les événements Charger le fichier, Insérer un texte, Insérer un caractère, et Enregistrer et quitter provoquent des transitions dans l'automate à états. L'automate à états pour le programme d'édition est décrit dans la Figure 1 ci-dessous.

Diagramme décrit dans le libellé.

Figure 2. automate à états pour un simple programme d'édition.

Etats Haut de la page

Un état est une condition d'un objet dans laquelle il effectue une activité ou attend un événement. Un objet peut rester dans un état pendant une période limitée. Un état possède plusieurs propriétés :

Nom Une chaîne textuelle distinguant l'état d'autres états ; un état peut également être anonyme, ce qui signifie qu'il n'a pas de nom.
Actions d'entrée/sortie Actions exécutées lors de l'entrée ou de la sortie de l'état.
Transitions internes Transitions traitées sans provoquer de changement dans l'état.
Sous-états La structure imbriquée d'un état, comprenant des sous-états discontinus (actifs séquentiellement) ou simultanés (actifs simultanément).
Evénements reportés Une liste d'événements qui ne sont pas traités dans cet état mais sont reportés et mis en file d'attente afin d'être traités par l'objet dans un autre état.

Ainsi que le montre la figure 1, deux états spécifiques peuvent être définis par l'automate à états d'un objet. L'état initial indique l'emplacement de départ par défaut de l'automate à états ou sous-état. Un état initial apparaît comme un cercle plein noir. L'état final indique la fin de l'exécution de l'automate à états ou le fait que l'état de fermeture a été atteint. Un état final est représenté comme un cercle plein noir entouré par un cercle non rempli. Les états initiaux et finaux sont en fait des pseudo-états. Ils ne contiennent pas les parties habituelles d'un état normal, à l'exception d'un nom. Une transition d'un état initial à un état final peut posséder toutes les fonctions, y compris une condition de garde et une action, mais ne possédera peut-être pas d'événement déclencheur.

Transitions Haut de la page

Une transition est une relation entre deux états indiquant qu'un objet du premier état effectuera certaines actions et entrera dans un second état lorsqu'un événement donné aura lieu et que les conditions spécifiées seront satisfaites. Lors de ce type de changement d'état, on dit que la transition "se déclenche". Avant que la transition ne se déclenche, on dit que l'objet est dans l'état "source" ; après le déclenchement, on dit qu'il est dans l'état "cible". Une transition a plusieurs propriétés :

Etat source L'état affecté par la transition ; si un objet est dans l'état source, une transition sortante peut se déclencher lorsque l'objet reçoit l'événement déclencheur de la transition et si la condition de garde, s'il en existe une, est satisfaite.
Déclencheur d'événement L'événement qui permet à la transition de se déclencher (si sa condition de garde est satisfaite) lorsqu'elle est reçue par l'objet dans l'état source.
Condition de garde Une expression booléenne évaluée lorsque la transition est déclenchée par la réception du déclencheur d'événement ; si l'expression évalue Vrai, la transition peut se déclencher ; si l'expression évalue Faux, la transition ne se déclenche pas. Si aucune autre transition ne peut être déclenchée par le même événement, l'événement est perdu.
Action Un calcul atomique exécutable qui peut agir directement sur l'objet auquel appartient l'automate à états, et indirectement sur d'autres objets qui sont visibles par l'objet.
Etat cible L'état actif après la fin de la transition.

Une transition peut avoir de nombreuses sources, auquel cas elle représente une jointure de nombreux états simultanés, ainsi que de nombreuses cibles, auquel cas elle représente une fourchette vers de nombreux états simultanés.

Déclencheurs d'événements

Dans le contexte d'un automate à états, un événement est une occurrence d'un stimulus qui peut déclencher une transition d'état. Les événements peuvent inclure des événements de signal, des événements d'appel, l'écoulement du temps, ou un changement d'état. Un signal ou appel peut posséder des paramètres dont les valeurs sont disponibles pour la transition, y compris des expressions pour les conditions de garde et l'action. Une transition sans déclencheur est également possible, et elle est représentée par une transition sans déclencheur d'événement. Ces transitions, également appelées transitions d'achèvement, sont déclenchées implicitement lorsque son état source a terminé son activité.

Conditions de garde

Une condition de garde est évaluée après que l'événement déclencheur de la transition ait eu lieu. Il est possible d'avoir des transitions multiples à partir du même état source et avec le même déclencheur d'événement, dans la mesure où les conditions de garde ne se chevauchent pas. Une condition de garde est évaluée une seule fois pour la transition au moment où l'événement a lieu. L'expression booléenne peut référencer l'état de l'objet.

Actions

Une action est un calcul atomique exécutable, ce qui signifie qu'il ne peut pas être interrompu et s'exécute donc jusqu'à ce qu'il soit terminé. Il s'oppose ainsi à une activité, qui peut être interrompue par d'autres événements. Les actions peuvent inclure les appels d'opérations (au propriétaire de l'automate à états ainsi qu'à d'autres objets visibles), la création ou la destruction d'un autre objet, ou l'envoi d'un signal à un autre objet. Dans le cas de l'envoi d'un signal, le nom du signal est précédé sur mot clé "envoyer".

Actions d'entrée et de sortie

Les actions d'entrée et de sortie permettent à la même action d'être répartie à chaque fois, respectivement, que l'on entre ou que l'on sort de l'état. Les actions d'entrée et de sortie permettent d'effectuer cette tâche soigneusement, sans avoir à placer les actions explicitement sur chaque transition entrante ou sortante. Les actions d'entrée et de sortie peuvent ne pas avoir d'arguments ni de conditions de garde. Les actions d'entrée générales d'un automate à états pour un élément de modèle peuvent avoir des paramètres représentant les arguments que la machine reçoit lors de la création de l'élément.

Transitions internes

Les transitions internes permettent aux événements d'être traités dans l'état, sans le quitter, ce qui évite de déclencher des actions d'entrée ou de sortie. Les transitions internes peuvent posséder des événements avec des paramètres et des conditions de garde, et représentent essentiellement les gestionnaires d'interruption.

Evénements reportés

Les événements reportés sont ceux dont le traitement est reporté jusqu'à un état dans lequel l'événement n'est plus reporté et devient actif. Lorsque cet état devient actif, l'occurrence d'événement est déclenchée et peut entraîner des transitions comme s'il avait juste eu lieu. L'implémentation des événements reportés nécessite la présence d'une file d'attente interne d'événements. Si un événement a lieu mais est défini comme reporté, il est mis en d'attente. Les événements sont retirés de la file d'attente dès que l'objet entre dans un état qui ne reporte pas ces événements.

Sous-états Haut de la page

Un état simple n'a pas de sous-structure. Un état possédant des sous-états (états imbriqués) est appelé état composite. Les sous-états peuvent être imbriqués à tout niveau. Un automate à états imbriqué peut avoir au maximum un état initial et un état final. Des sous-états sont utilisés pour simplifier les automates à états plats et complexes en montrant que certains états ne sont possibles que dans un contexte spécifique (l'état de fermeture).

Diagrammes montrant les sous-états.

Figure 3. Sous-états.

A partir d'une source extérieure à un état composite de fermeture, une transition peut cibler l'état composite ou bien un sous-état. Si sa cible est l'état composite, l'automate à états imbriqué doit inclure un état initial, auquel le contrôle passe après l'entrée dans l'état composite et une fois que son action d'entrée (si elle existe) a été répartie. Si sa cible est l'état imbriqué, le contrôle passe à l'état imbriqué après avoir réparti l'action d'entrée de l'état composite (si elle existe), puis l'action d'entrée de l'état imbriqué (si elle existe).

Une transition partant d'un état composite peut avoir à sa source l'état composite d'un sous-état. Dans les deux cas, le contrôle quitte d'abord l'état imbriqué (et sa sortie, si elle existe, est répartie), puis quitte l'état composite (et sa sortie, si elle existe, est répartie). Une transition ayant pour source l'état composite interrompt essentiellement l'activité de l'automate à états imbriqué.

Etats historiques Haut de la page

A moins d'une précision contraire, lorsqu'une transition entre dans un état composite, l'action de l'automate à états imbriqué recommence à l'état initial (à moins que la transition ne cible directement un sous-état). Les états historiques permettent à l'automate à états d'entrer à nouveau dans le dernier sous-état actif avant de quitter l'état composite. Nous présentons dans la Figure 3 un exemple d'état historique.

Diagramme montrant les états historiques.

Figure 4. Etat historique.

Techniques communes de modélisation Haut de la page

Les automates à états sont généralement utilisés pour modéliser le comportement d'un objet tout au long de sa vie. Ils sont particulièrement utiles lorsque les objets ont un comportement dépendant des états. Les objets pouvant posséder des automates à états incluent des classes, des sous-systèmes, des cas d'utilisation et des interfaces (pour appuyer des états qui doivent être atteints par l'objet qui réalise l'interface).

Tous les objets ne requièrent pas d'automates à états. Si le comportement d'un objet est simple, par exemple s'il se contente de stocker ou de récupérer des données, le comportement de l'objet ne dépend pas de l'état et un automate à états présente alors peu d'intérêt.

La modélisation de la durée de vie d'un objet implique trois éléments : préciser les événements auxquels l'objet peut répondre, la réponse à ces événements, et l'impact du passé sur le comportement actuel. La modélisation de la durée de vie d'un objet implique également de décider de l'ordre judicieux dans lequel l'objet peut répondre aux événements, en commençant lors de la création de l'objet et en continuant jusqu'à sa destruction.

Pour modéliser la durée de vie d'un objet :

  • Définissez le contexte pour l'automate à états, qu'il s'agisse d'une classe, d'un cas d'utilisation, ou du système global.
    • Si le contexte est une classe ou un cas d'utilisation, rassemblez les classes voisines, y compris les classes parentes ou les classes pouvant être atteintes par des associations ou des dépendances. Ces voisins sont des cibles potentielles pour les actions et des cibles pouvant être potentiellement inclues dans les conditions de garde.
    • Si le contexte est le système dans son ensemble, réduisez votre cible à un comportement du système, puis examinez les durées de vie des objets impliqués dans cet aspect. La durée de vie du système complet est trop importante pour représenter une cible judicieuse.
  • Etablissez les états initiaux et finaux pour l'objet. S'il y a des préconditions ou des post-conditions des états initiaux et finaux, définissez-les également.
  • Déterminez les événements auxquels l'objet répond. On peut les trouver dans les interfaces de l'objet.
  • En allant de l'état initial à l'état final, décrivez les états globaux dans lesquels le projet peut se trouver. Connectez ces états avec des transitions déclenchées par les événements appropriés. Continuez en ajoutant ces transitions.
  • Identifiez toutes les actions d'entrée ou de sortie.
  • Etendez ou simplifiez l'automate à états en utilisant des sous-états.
  • Vérifiez que tous les événements déclenchant des transitions dans l'automate à états correspondent aux événements prévus par les interfaces réalisées par l'objet. De même, vérifiez que tous les événements prévus par les interfaces de l'objet sont traités par l'automate à états. vous souhaitez explicitement ignorer des événements (par exemple les événements reportés).
  • Vérifiez que toutes les actions de l'automate à états sont prises en charge par les relations, les méthodes et les opérations de l'objet de fermeture.
  • Examinez l'automate à états en le comparant aux séquences d'événements prévus et à leurs réponses. Cherchez les états inatteignables et ceux qui posent problème à l'automate.
  • Si vous réarrangez ou restructurez l'automate à états, assurez-vous que la sémantique n'a pas changé.

Conseils et astuces Haut de la page

  • Lorsque vous avez le choix, utilisez la sémantique visuelle de l'automate à états plutôt que de rédiger des codes de transitions détaillés. Par exemple, ne déclenchez pas une transition sur plusieurs signaux, en utilisant ensuite le code détaillé pour gérer le flot de contrôle différemment selon le signal. Utilisez des transitions séparées, déclenchées par des signaux séparés. Evitez la logique conditionnelle qui, dans le code de transition, masque les comportements additionnels.
  • Nommez l'état selon ce que vous attendez de lui, ou bien ce qui se passe pendant cet état. Souvenez-vous qu'un état n'est pas un "moment précis" ; c'est une période pendant laquelle l'automate à états attend qu'un événement ait lieu. Par exemple "enattentedelafin" est un meilleur nom que "fin"; "programmeruneactivité" est meilleur que "temporisation". Ne nommez pas des états comme s'ils étaient des actions.
  • Nommez tous les états et les transitions d'un automate à états de façon unique ; cela facilitera le déboguage à la source.
  • Utilisez les variables d'états (attributs utilisés pour contrôler le comportement) avec précaution ; ne les utilisez pas pour remplacer la création de nouveaux états. Lorsqu'il y a peu d'états, avec un comportement ne dépendant pas ou très peu de l'état, et lorsque aucun ou peu de comportements fonctionnant simultanément ou étant indépendants de l'objet contenant l'automate à états, des variables d'état peuvent être utilisées. S'il existe des comportements complexes et dépendants des états potentiellement simultanés, ou si les événements qui doivent être traités peuvent trouver leur source à l'extérieur de l'objet contenant l'automate à états, envisagez d'utiliser une collaboration de deux objets actifs ou plus (peut-être définie en tant que composition).
  • S'il y a plus de 52 états sur un seul diagramme, envisagez l'utilisation de sous-états. C'est une question de logique : dix états dans un modèle tout à fait classique peuvent convenir, mais s'il y a deux états possédant quarante transitions entre eux, il faut réexaminer la situation. Assurez-vous que l'automate à états est compréhensible.
  • Nommez les transitions pour ce qui déclenche l'événement et/ou ce qu'il se passe pendant la transition. Choisissez des noms qui favorisent la compréhension.
  • Lorsque vous voyez un sommet de choix, demandez-vous si vous pouvez déléguer la responsabilité de ce choix à un autre composant, afin qu'il soit présenté à l'objet comme un ensemble de signaux distincts sur lesquels agir (par exemple, plutôt que de choisir sur msg->data > x), faites prendre la décision à un autre acteur intermédiaire et envoyez un signal avec la décision explicite dans le nom du signal (par exemple, utilisez des signaux appelés estplein et estvide au lieu d'utiliser un signal appelé valeur et de devoir vérifier les données du message).
  • Nommez la question répondue au sommet de choix de façon descriptive, par exemple "reste-t-ildelavie" ou "est-celemomentdeseplaindre".
  • Dans un objet donné, essayez de donner des noms uniques au sommet de choix (pour la même raison qu'il faut donner des noms uniques aux noms de transition).
  • Y-a-t-il des fragments de code trop longs sur les transitions ? Est-il préférable d'utiliser des fonctions, ou les fragments de code communs sont-ils consignés comme des fonctions ? Une transition doit se lire comme un pseudo-code global, et doit respecter les mêmes règles de longueur ou même des règles plus strictes que les fonctions C++. Par exemple, une transition possédant plus de 25 lignes de code est considérée comme excessivement longue.
  • Les fonctions doivent être nommées selon ce qu'elles font.
  • Examinez avec un soin particulier les actions d'entrée et de sortie : il est très facile de faire des changements et d'oublier de changer les actions d'entrée et de sortie.
  • Les sorties peuvent être utilisées pour fournir des fonctions de sécurité- par exemple la sortie de l'état "réchaudallumé" éteint le réchaud - les actions étant alors utilisées pour réaliser une assertion.
  • Généralement les sous-états doivent contenir deux états ou plus à moins que l'automate à états soit abstrait et qu'il soit affiné par les sous-classes de l'élément de fermeture.
  • Des points de choix doivent être utilisés plutôt que la logique conditionnelle dans les actions ou les transitions. Les points de choix sont vus facilement, alors que la logique conditionnelle dans le code est masquée et facile à négliger.
  • Evitez les conditions de garde
    • Si l'événement déclenche plusieurs conditions, il n'y a aucun contrôle sur la condition de garde évaluée au départ. Ainsi, les résultats peuvent être imprévisibles.
    • Plus d'une condition de garde peut être "vraie", mais seule une transition doit être suivie. Le chemin choisi peut être imprévisible.
    • Les conditions de garde ne sont pas visuelles ; il est plus difficile de "voir" leur présence.
  • Evitez les automates à états qui ressemblent à des diagrammes d'états.
    • Ils peuvent indiquer une tentative de modélisation d'une abstraction qui n'est pas réellement présente, comme :
      • en utilisant une classe active pour modéliser un comportement mieux adapté à une classe (ou à des données) passive(s) ou
      • en modélisant une classe de données en utilisant une classe de données et une classe active étroitement couplés (par exemple, la classe de données a été utilisée pour transmettre des informations mais la majorité des données contenues dans la classe active doit être associée à la classe de données.
    • Cette mauvaise utilisation des automates à états peut se reconnaître aux symptômes suivants :
      • message envoyé à "lui-même", principalement pour réutiliser le code
      • peu d'états, avec de nombreux points de choix
      • dans certains cas un automate à états sans cycles. Ce type d'automates à états est valide dans des applications de contrôle des processus ou lorsque vous essayez de contrôler une séquence d'événements ; leur présence pendant l'analyse représente généralement la dégénération d'un automate à états en organigramme.
    • Lorsque le problème est identifié :
      • Envisagez de séparer la classe active en unités plus petites possédant des responsabilités plus distinctes,
      • Déplacez plus de comportements dans une classe de données associée à la classe active qui pose problème.
      • Déplacez plus de comportements dans des fonctions de classe active.
      • Créez plus de signaux pertinents plutôt que de vous appuyer sur les données.

Concevoir avec des automates à états abstraitsHaut de la page

Un automate à états abstrait est un automate à états auxquels il est nécessaire d'ajouter plus de détails avant de pouvoir l'utiliser pour des objectifs pratiques. Les automates à états abstraits peuvent être utilisés pour définir des comportements génériques et réutilisables qui sont affinés plus en détails dans les éléments de modèles supplémentaires.

Diagramme décrit dans le libellé.

Figure 5. Un automate à états abstrait.

Examinez l'automate à états abstrait de la Figure 5. L'automate à états simple décrit représente le niveau de comportement le plus abstrait (l'"automatisation de contrôle") de nombreux différents types d'éléments dans les systèmes événementiels. Bien qu'ils partagent tous cette forme générale, les différents types d'éléments peuvent posséder des comportements plus ou moins détaillés dans l'état d'exécution selon leur fonction. Ainsi, cet automate à états sera probablement défini dans une classe abstraite qui sert de classe racine pour les diverses classes actives spécialisées

Ainsi, définissons deux de ces types de décomposition de cet automate à états abstrait, en utilisant l'héritage. Ces deux décompositions, R1 et R2, sont montrées dans la Figure 6. Pour plus de clarté, nous avons dessiné les éléments hérités de la classe parente en utilisant un crayon gris.

Diagramme décrit dans le libellé.

Figure 6. Deux décompositions de l'automate à états en Figure 5.

Les deux décompositions diffèrent largement dans leur manière de décomposer l'état d'exécution et également d'étendre la transition "départ" d'origine. Bien sûr, ces choix peuvent être faits seulement lorsque la décomposition est connue et ne peut pas avoir être effectuée avec une seule transition de bout en bout dans la classe abstraite.

Etats de chaîne Haut de la page

La capacité de "continuer" les transitions entrantes et sortantes est cruciale pour le type de décomposition décrit ci-dessus. Les points d'entrée et les états finaux, associés à des transitions de continuation, semblent suffire pour fournir cette sémantique. Malheureusement, cela ne suffit pas lorsque de nombreuses transitions différentes doivent être étendues.

Le modèle de comportement abstrait doit permettre d'enchaîner deux segments de transition ou plus qui sont tous exécutés dans la portée d'une seule étape d'exécution-jusqu'à-la-fin. Cela signifie que les transitions entrant dans un état hiérarchique sont séparées entre la partie entrante qui s'achève sur la frontière d'état, et une extension qui continue dans l'état. De même, les transitions sortantes émanant d'un état imbriqué hiérarchiquement sont segmentées en une partie qui s'achève sur la frontière d'état de fermeture, et une partie qui continue de la frontière d'état à l'état cible. On peut obtenir cet effet dans UML en introduisant le concept d'état chaîne. Cet élément est modélisé par un stéréotype (<<étatchaîne>>) du concept d'état de l'UML. Il s'agit d'un état dont l'unique objectif est d'"enchaîner" d'autres transitions automatiques (sans déclencheur) dans une transition d'entrée. Un état chaîne n'a pas de structure interne- pas d'action d'entrée, pas d'activité interne, pas d'action de sortie. Il n'a pas non plus de transitions déclenchées par les événements. Il peut avoir un certain nombre de transitions d'entrée. Il peut avoir une transition de sortie sans événement déclencheur ; cette transition se déclenche automatiquement lorsqu'une transition d'entrée active l'état. L'objectif de l'état est d'enchaîner une transition d'entrée à une transition de sortie séparée. Entre la ou les transition(s) d'entrée et la transition de sortie enchaînée, l'une est connectée à un autre état à l'intérieur de l'état contenant et l'autre est connectée à un autre état à l'extérieur de l'état contenant. L'objectif de l'introduction d'un état chaîne est de séparer la spécification interne de l'état contenant de son environnement externe ; c'est une question d'encapsulation.

En effet, un état chaîne représente un état d'"émulation" qui sert à enchaîner une transition à une transition de continuation spécifique. Si aucune transition de continuation n'est définie, la transition s'achève dans l'état chaîne, et une transition sur un état de fermeture doit ensuite se déclencher pour faire évoluer la situation.

L'exemple d'un segment d'automate à états dans la Figure 7 illustre les états chaîne et leur notation. Les états chaîne sont représentés dans un diagramme d'automate à états par des petits cercles blancs situés dans l'état hiérarchique approprié (cette notation est similaire aux états initiaux et finaux, auxquels ils ressemblent). Les cercles sont des icônes de stéréotypes du stéréotype de l'état chaîne et sont généralement dessinés près de la frontière pour des raisons pratiques. (En fait, une variation de notation consisterait à les dessiner sur la frontière de l'état de fermeture.)

Diagramme décrit dans le texte d'accompagnement.

Figure 7. Etats chaîne et transitions enchaînées.

La transition enchaînée de cet exemple consiste des trois segments de transition enchaînée e1/a11-/a12-/a13. Lorsque le signal e1 est reçu, la transition appelée e1/a11 est prise, son action a11 est exécutée, puis l'état chaîne c1 est atteint. Ensuite, la transition de continuation entre c1 et c2 est prise, et, finalement, dans la mesure où c2 est également un état chaîne, la transition de c2 à S21 est également prise. Si les états le long de ces chemins ont des actions de sortie et d'entrée, la véritable séquence d'exécution d'actions est la suivante :

  • sortie de S11
  • action a11
  • sortie de S1
  • action a12
  • entrée de S2
  • action a13
  • entrée de S21

Toutes ces actions sont exécutées dans la portée d'une seule étape d'exécution-jusqu'à-la-fin.

On peut le comparer à la sémantique d'exécution d'action de la transition directe e2/a2, qui est la suivante :

  • sortie de S11
  • sortie de S1
  • action a2
  • entrée de l'état S2
  • entrée de l'état S21


RUP (Rational Unified Process)   2003.06.15