L'architecture de composants de Zope en 3D
La reproduction d'un petit thread Twitter où je reprenais les illustrations 3D faites avec Blender pour ma première conférence à PyconFR 2008.
Adaptateur simple
L'idée est de donner l'exemple d'une application de blog. Le truc classique à l'époque pour voir ce que peut faire un framework. On commence donc avec la représentation d'un objet Blog. C'est rond, c'est plein, il y a du code dedans.
Un objet Python seul c'est bien, mais c'est insuffisant. Ça ressemble à une boite noire (ou une sphère orange), et on ne sait pas ce qu'on peut faire avec. Donc on ajoute une interface.
Une interface est comme un panneau de commande qu'on ajoute devant l'objet. Elle ne contient rien, donc elle est plate, mais elle permet de donner accès à des fonctionnalités de l'objet.
Ensuite, notre objet Blog ne sait quand-même toujours pas faire grand chose, à part créer des posts de blog. On aimerait avoir accès d'autres fonctionnalités, comme la gestion de la taille du blog. Par exemple le nombre de posts du blog. Donc on ajoute une autre interface devant.
Comment fait-on pour accéder à des fonctionnalités offertes par une nouvelle interface, quand on a à notre disposition une autre interface ? On ajoute un adaptateur entre les deux. L'adaptateur s'adapte à notre objet Blog et fournit une nouvelle interface.
On remplace l'héritage objet par de la délégation : la fonctionnalité est déléguée à un autre objet, qu'on appelle un composant. C'est très utile pour séparer les fonctionnalités, et les réutiliser dans d'autre contextes. Pour ça il nous faut un registre de composants.
Comme on est en Python, l'adaptateur peut bien faire ce qu'il veut, et accéder par n'importe quel trou aux données de l'objet auquel il s'adapte. Ça marche car l'adaptateur est spécifique à l'objet auquel il s'adapte. Ce qui est générique est l'interface.
Interfaces marqueur
Après le cas de l'adaptateur simple, voyons maintenant le cas des interfaces marqueurs. Certaines fonctionnalités comme la gestion des metadonnées et des commentaires ne sont pas spécifiques à un blog, et peuvent être réutilisées partout, sans même écrire d'adaptateur spécifique.
On ajoute une nouvelle interface de gestion de métadonnées à notre Blog.
Pour cette interface, on a un adaptateur qui est déjà disponible et qui marche pour n'importe quel objet. On l'inscrit dans le registre, afin qu'il maintenant soit dispo au runtime, sans relancer l'appli.
Ces interfaces sont dites « marqueur » car elles permettent de marquer un objet comme étant capable de fournir une fonctionnalité. Leur nom termine souvent en « ...able ». Ici on déclare ensuite que notre blog est « commentable ».
Comme le blog est maintenant « commentable », l'objet peut bénéficier d'un adaptateur générique qui offre des commentaires. Un adaptateur qu'on a éventuellement écrit pour une autre appli.
La séparation est très bonne, on peut embarquer les fonctionnalités dans des paquets Python différents, et les distribuer indépendamment. D'ailleurs le paquet du dessus zc.comment devait exister pour de vrai. https://pypi.org/project/zc.comment/Le paquet du dessous est notre application.
Quelques cas d'utilisation des adaptateurs simples :
- Métadonnées (date de création, créateur, tags)
- Commentaires
- URL d'un objet
- Traversing
- Taille
- Catégorie
- Texte à indexer
- Vignette d'aperçu
Doubles adaptateurs
Passons à la gestion des vues. C'est à dire de l'affichage de notre blog. On a d'un côté notre objet blog,et de l'autre le navigateur. Que faut-il mettre en les deux ? Petit rappel au passage, Zope était un framework de publication d'objets. Pas de SQL. Pas d'ORM. Que des objets.
Le navigateur envoie une requête HTTP, qui traverse le Publisher.
Avec la requête HTTP, le Publisher crée alors un objet Requete. Cet objet offre une interface.
On a donc DEUX interfaces à notre disposition. Celle de l'objet Blog qu'on veut afficher, et celle de la Requête. Mais à la fin on voudrait accéder aux fonctionnalités d'une Page web, qui ne sont décrites que par une seule interface. On a besoin d'un double adaptateur !
Cet adaptateur correspond à la vue. Si on veut avoir plusieurs types de vues, par exemple une vue Edit et une vue View, on peut inscrire plusieurs adaptateurs dans le registre.
Lorsqu'on inscrit la vue dans le registre, on peut préciser quel template on veut. Ça pouvait être du Jinja, des ZPT, du Chameleon ou n'importe quel autre langage de template web.
On a vu le cas des adaptateurs simples, qui s'adaptent à un objet, et des adaptateurs doubles qui s'adaptent à deux objets. On pouvait aussi créer des triple voire quadruple adaptateurs. J'ai un peu oublié les cas d'usage, mais c'était possible.
Utilities
À l'autre extrémité, il y avait les adaptateurs qui ne s'adaptent à aucune interface, et qui se contentaient d'offrir l'accès à une interface. Ils s'appelaient des « utilities ». Ici par exemple différents types de post de blog avec différents formats (HTML, RST, OpenDocument).