points de vue

les déambulations d'un codeur

Aller au contenu | Aller au menu | Aller à la recherche

Une histoire de slots

card slotL’amélioration de la structuration du code d’un programme, avec la distinction des considérations techniques de celles métier, est le Saint Graal que poursuivent sans fins les développeurs. A cette fin, de nombreuses techniques ont fait leur apparition dont nous pouvons citer les traits ou les annotations. A côté de ceux-ci, il existe une technique élégante et uniforme que sont les slots. Mais, que sont ces derniers et en quoi peuvent ils nous aider dans notre quête ?

Un adage veut qu’un bon développeur soit un développeur paresseux. Ce qui se cache derrière cette paresse est l’aptitude du codeur à automatiser ses tâches redondantes et souvent ennuyeuses et de tout faire pour faciliter son boulot. L’avantage de cette attitude est évidemment pour l’organisation un gain de productivité à terme. En fait, à y regarder de près, le développeur ne fait que s’aligner aux lois de la physique : minimiser l’entropie. Un des aspects de cette caractéristique est, pour le programmeur, de minimiser la duplication de codes et, pour ce faire, il va user de techniques et de moyens qu’il connaît mais aussi qu’il a à sa disposition via l’outillage et surtout son langage de programmation. La structuration du code est l’une de ces techniques. Elle est vieille de plus de 30 ans mais n’a cessé et ne cesse de continuer à évoluer. L‘AOP (Aspect-Oriented Programming), les traits, les mixins, les closures, etc. ne sont que des aspects de celle-ci dans leur objectif de modulariser non seulement le code métier mais aussi et surtout le code transversal au métier et aux fonctionnalités du logiciel. Avec l‘AOP, nous pouvons définir des composants d’ordre technique comme la génération de traces ou la validation des autorisations d’appel d’opérations. Ces composants sont ensuite tissés aux objets métiers à l’exécution ou à la compilation ; l‘AOP permet de maintenir d’un côté les caractéristiques techniques et de l’autre les modules métiers sans les entacher de considération techniques. Les mixins et les traits sont deux concepts différents permettant de définir des propriétés, d’ordre technique ou fonctionnelle, transversales aux objets métiers puis de les associer à ces derniers de manière statique ou dynamique. Par exemple, l’ordonnancement ou encore la persistance peut être définie dans un mixin ou un trait, indépendamment des objets métiers des applications. Ces deux techniques ont été popularisés respectivement par les langages Ruby et Self. Les annotations, popularisés par Java, constituent une autre technique qui permet de qualifier sémantiquement des objets et d’attacher à celles-ci un comportement qui peut aller jusqu’à la génération de codes ; par exemple, des objets peuvent être annotés avec des marqueurs de gestion des transactions ou encore d’annotations métiers propres au domaine de l’application.

Pourtant, il existe un autre concept popularisé par Self en même temps que les traits : les slots. Ces derniers ne sont pas nouveaux puisqu’ils furent introduit par CLOS (Common Lisp Object System). (Dans CLOS comme dans Self, ils sont appelés descripteurs de slot). On retrouve ces derniers dans le langage Io et actuellement un travail est réalisé pour les intégrer à terme dans Pharo. Mais qu’est-ce qu’un slot ou descripteur de slot ? Dans le contexte d’un langage orienté-objet, un slot est la réification du point d’accès aux propriétés d’un objet ou, plus exactement, du mécanisme d’envoi/réception de messages (cf. mon billet sur les différentes POO). Tout accès aux propriétés d’un objet se fait par l’intermédiaire des slots qui, non seulement peuvent contrôler l’accès en lecture et en écriture de ces propriétés, mais aussi contenir des informations sémantiques sur celles-ci. Ils constituent une interface homogène d’accès aux propriétés de l’objet. Dans Self et Newspeak, le slot est un objet particulier qui agit comme une méthode retournant toujours une valeur (que celle-ci soit calculée dans le cas d’une méthode ou mémorisée dans le cas d’un attribut). Selon les langages de programmation, les slots peuvent n’être définis que pour l’accès aux champs d’un objet. Parce que c’est aussi un objet, le slot peut être manipulé comme n’importe quel autre objet du langage et, par voie de conséquence, il est possible alors de lui affecter aussi un comportement. Pour illustrer ceci, voici un petit exemple dans un pseudo-langage dans lequel le caractère point représente un slot (l’accès à un slot se fait par le point) :

Point.x := 3
Point.move := (abs, ord) { myself x += abs; myself y += ord; myself }
Point.move.afterInvocation := () { View current updateView(myself) }

A la première ligne, le slot réfère un champs x tandis qu’à la seconde ligne le slot réfère une opération move. Le premier retournera la valeur 3 tandis que le second, une fois son action accomplie, retournera par défaut le point lui même. La dernière ligne spécifie quoi faire à la suite de l’invocation de l’opération : mettre à jour l’IHM dans laquelle est dessiné le point. L’attribut myself des slots désigne l’instance de l’objet qui contient le slot. Dans la représentation ci-dessus, par homogénéité, les propriétés d’un slot (par exemple afterInvocation) sont elles aussi des slots (dans ce cas, il existe un slot terminal qui référence ou stocke directement la valeur de l’attribut ou les instructions de la méthode). Nous aurions pu écrire le code comme suit pour plus de lisibilité :

Point setSlot($x, 3)
Point setSlot($move, (abs, ord) { myself x += abs; myself y += ord; myself } )
Point.move setSlot($afterInvocation, () { View current updateView(myself) } )

dans lequel le signe $ désigne un symbole.

Parce qu’un slot peut représenter un point d’accès vers un autre objet, les relations inter-objets deviennent mécaniquement des citoyens de première classe au même titre que l’objet (ou la classe dans un langage orienté-classes). Pour illustrer ceci, imaginons un employeur qui a plusieurs employés et des employés qui est rattaché à un et un seul employeur :

Employer.employees := []
Employer.employees.onWrite := (e) { (e employer = myself) ifFalse(
  { e employer(myself) })
}

Employee.employer := None(Employer)
Employee.employer.onWrite : = (e) { (e employees contains(myself)) ifFalse(
  { e employees add(myself) })
}

Dans le code ci-dessus, chaque nouveau employé de l’employeur mettra automatiquement la référence employer de l’employé avec son nouveau employeur. De même, chaque mise-à-jour de l’employeur de l’employé ajoutera ce dernier parmi les employés de son nouveau employeur :

anEmployee := Employee()
anEmployer := Employer()
anEmployer employees add(anEmployee)
Assertion assertThat(anEmployee employer, is(anEmployer))

Les slots employees et employer représentent donc des relations qui peuvent être manipulés comme de simples objets et qui permettent de maintenir la cohérence des relations entre l’employeur et les employés. Nous pouvons alors introduire un mécanisme de création et de relations hiérarchiques de slots comme avec les objets (ou les classes d’objets) :

ManyToOneSlot := Slot {
  oppositeSlot: Slot,
  oppositeClass: Class,
  initialize: (anInstance, theOppositeSlot, theOppositeClass) {
    myself := anInstance
    oppositeClass := System class(theOppositeClass)
    oppositeSlot := oppositeClass slot(theOppositeSlot)
  },  
  onWrite: (anInstance) {
    ((oppositeSlot read: anInstance) = myself ) ifFalse(
      { oppositeSlot write(myself, anInstance) } )
  } 
}

OneToManySlot := Slot {
  oppositeSlot: Slot,
  oppositeClass: Class,
  initialize: (anInstance, theOppositeSlot, theOppositeClass) {
    myself := anInstance
    oppositeClass := System class(theOppositeClass)
    oppositeSlot := oppositeClass slot(theOppositeSlot)
  },  
  onWrite: (anInstance) {
    ((oppositeSlot read(anInstance)) contains(myself) ) ifFalse(
      { oppositeSlot write(myself, anInstance) } )
  } 
}

Employer := Object {
   employees: ManyToOneSlot(self, $employer, $Employee)
}

Employee := Object {
   employer: OneToManySlot(self, $employees, $Employer)
}

De la même façon, il est alors possible de définir des slots dédiés à la persistance ou encore de combiner les slots entre eux pour réaliser des traitements transverses. Ceci et le fait d’ajouter du comportement aux slots ouvrent la porte à la méta-programmation, à la réflexion, sans commune mesure avec les autres concepts. Ce que permettent l’AOP, les annotations, certains usages des mixins et des traits, peuvent toutes être réalisés par les slots et ceci d’une manière uniforme et cohérente avec les concepts de base du langage.

Ce petit billet vous a donné un petite présentation du concept de slot, illustrée avec un pseudo-langage. J’espère qu’il vous aura donné un aperçu de la puissance et de l’expressivité qui se cache derrière ce simple concept.

Miguel Moquillon

Auteur: Miguel Moquillon

Restez au courant de l'actualité et abonnez-vous au Flux RSS de cette catégorie

Commentaires (0)

Soyez le premier à réagir sur cet article

Ajouter un commentaire Fil des commentaires de ce billet

no attachment



À voir également

L'égalité d'identité et l'égalité de valeur en Java

Dans certains langages de programmation, comme Java, il n’y a pas de méthodes ou d’opérateurs distincts entre l’égalité d’identité et celle de valeur. Si, dans un programme classique écrit dans un langage comme Java, l’égalité d’identité (de l’OID pour Object IDentifier) pourrait se faire avec l’opérateur == et celle de valeur avec la méthode equals surchargée, il n’en va plus de même dès qu’il s’agit d’objets persistés. Et là, in fine, c’est le drame : que compare t’on avec la méthode equals ? la valeur des objets ou leur identité ?

Lire la suite

L'approche Micro-Services et le paradigme Orienté-Objet

J’aime à dire que l’évolution en informatique ne connait que très peu de ruptures et ressemble à une grande spirale dans laquelle les nouvelles technologies et approches ne sont que des reprises de plus anciennes que l’on a dépoussiéré et adapté aux attentes et au temps actuels ; c’est ce que l’on appelle l’innovation. Les micro-services, le grand buzz de l’année 2015, n’échappent pas à cette régle. (On est friand aussi de buzz en informatique). Mais qu’est-ce que les micro-services ? En fait, rien de spécial. Ce n’est ni plus ni moins que le découpage des responsabilités des applications dans des services Web dédiés et qui communiquent entre eux par messages. Du SOA ? Du REST ? … Oui, tout ça mais ce n’est plus à la mode, il faut parler maintenant de micro-services.

Lire la suite