Des composants qui hébergent des variables et des tâches
Le modèle structurel d’NJN a été choisi pour faciliter le développement rapide d’applications distribuées. Il est orienté composant. Ce qui signifie qu’une application NJN est une construction hiérarchique élaborée à partir de composants standards, disponibles dans des bibliothèques. Les composants hébergent des tâches et des variables, seuls éléments qui laisseront leur marque dans l’exécutif. A ce modèle de base s’ajoutent quelques objets plus complexes à appréhender, les méthodes et les canaux, destinés à structurer les interconnexions ou à abstraire les communications au sein de l’application. Ce chapitre expose les différents objets présents dans le modèle structurel d’NJN. Après une première partie générale où quelques repères sont posés, chaque famille d’objet est présentée avec ses caractéristiques essentielles. Le point de vue adopté est celui du développeur d’application. Le rôle des objets et leur comportement est décrit en détail. Quelques exemples de code viennent illustrer de façon concrète le propos.Enfin, chaque classe d’objet est associée à un modèle qui lui est spécifique, un pattern, qui renferme les informations nécessaires à la création de l’objet.
Les patterns sont rangés dans des paquetages et des bibliothèques.t une structure hiérarchique de composants. Les composants hébergent des tâches, des variables, des propriétés, des canaux, d’autres composants, etc. Chacun des éléments de cette architecture porte un nom visible localement.La portée des noms est définie par le conteneur (composant, canal ou vecteur) directement englobant. Par exemple, une variable définie dans un composant est accessible, via son nom, dans toutes les tâches hébergées par ce composant au même niveau hiérarchique.Appeler cette méthode depuis un composant pour récupérer un objet défini localement est donc la plupart du temps une erreur. La seule possibilité est de mémoriser dans une variable locale l’objet renvoyé par la fabrique njn_new(). Bien que pointant sur un objet temporairement invalide, la référence renvoyée est suffisante pour configurer l’objet futur.Rien n’interdit de prime abord d’accéder à un espace de noms quelconque si l’on dispose d’une référence sur le module qui lui correspond. En effet, tout module défini peut être transmis en premier argument à la méthode njn_get(). C’est ce qui est exploité dans l’exemple ci-dessous. njn_get(), la méthode njn_get_owner() renvoie le conteneur du module qu’on lui fournit en argument.
En associant ces deux méthodes, on accède à l’ensemble de l’application, bien que la technique soit un peu fastidieuse.La durée de vie des objets structurels dans une application NJN est parfaitement explicite. Par défaut, ils sont créés et détruits en même temps que leur conteneur. Mais il est toujours possible de raccourcir leur durée de vie. Dans l’exemple ci- dessous, la tâche name et lifeline déjà rencontrées. Elle signale les changements structurels infligés au corps de l’instance de composant. L’ajout d’une tâche ou d’une variable, le changement de nom d’une variable, la suppression d’un composant interne, etc. se traduisent par l’inscription d’un évènement sur cette propriété. La propriétéLe corps d’un composant définit sa structure interne, c’est-à-dire l’ensemble des objets qu’il renferme et la manière dont ils entrent en interaction pour produire le comportement attendu. Parmi les éléments du corps, on retrouve les signaux du port d’entrées/sorties. lifeline). A un instant donné, ne sont visibles dans le corps du composant que les objets dont la ligne de vie atteste de l’activité. Chacun de ces objets est accessible par son nom d’instance. var sont les données manipulées par les tâches de l’application. Leur type est géré dynamiquement. Elles pourraient être des variables au sens commun, à ceci près que leur comportement temporel diffère des variables classiquement rencontrées dans la plupart des langages de programmation. Les variables peuvent être déclarées en entrée ou en sortie.
Elles deviennent dans ce cas des éléments du port d’entrées/sorties du composant qui les héberge.t différent de ce qu’on observera dans la majorité des langages de programmation. Il se rapproche de celui des signaux du langage VHDL [57] ou des variables du langage SystemVerilog [58]2. Afin de garantir la causalité des évènements qui se produisent dans l’application, l’affectation d’une nouvelle valeur à une variable n’est jamais immédiatement observable. La remarque précédente en amène une seconde. Pour garantir la causalité de l’application, il est capital d’éviter toute affectation simultanée d’une même variable. Une manière de respecter cette règle est de faire en sorte qu’il n’existe qu’une seule source (une tâche ou une connexion) susceptible de modifier l’état de chaque variable. Les sources multiples sont donc permises mais à éviter autant que possible.