“doc” (Col. : Science Sup 17x24) — 2007/7/19 — 18:18 — page 260 — #270
i
i
i
i
i
i
i
i
260
5
• La programmation avec état explicite
➤ Le moins possible de niveaux d’indirection
Cette règle est apparentée à la précédente. Quand A a un pointeur vers B, alors une
mise à jour de B exige une mise à jour de A. Toute indirection est une dépendance.
L’idée est d’éviter que le pointeur devienne détaché : sa destination n’a plus de sens
pour la source. Toute action sur B peut causer le détachement du pointeur de A. Le
pointeur de A n’est pas connu par B et il ne peut donc pas empêcher cela. Une solution
provisoire est de ne jamais changer B, mais uniquement d’en faire des copies modifiées.
Cela pourra être valable si le système fait de la gestion automatique de mémoire.
Deux exemples typiques des pointeurs problématiques sont des liens symboliques
dans un système de fichiers Unix et les URL. Les liens symboliques sont pernicieux
pour la maintenance d’un système. Ils sont commodes parce qu’ils peuvent référencer
d’autres arborescences montées dans un système de fichiers, mais en fait ils sont une
grande source de problèmes. Les URL sont connus pour être peu sûrs. Ils sont souvent
référencés dans les documents imprimés, mais leur durée de vie est généralement
beaucoup plus courte que celle du document. C’est parce qu’ils peuvent devenir
détachés rapidement mais aussi parce que l’Internet n’a pas une grande qualité de
service.
➤ Des dépendances prévisibles
Prenons par exemple la commande « localiser » qui garantit de récupérer un fichier
sur un réseau et d’en faire une copie locale. Son comportement est simple et prévisible,
ce qui n’est pas le cas pour la mémoire cache dans les navigateurs Web. Le terme
cache est mal choisi parce qu’une vraie mémoire cache maintient une cohérence entre
l’entité originale et la copie. Pour toute mémoire cache, la politique de remplacement
des pages doit être clairement indiquée.
➤ La prise des décisions au bon niveau
Une décision temporisée (« time out ») doit être prise au bon niveau. Il est faux
d’implémenter une décision temporisée de façon irrévocable à un bas niveau du
système (un composant fortement imbriqué), qui propage jusqu’au niveau le plus haut
sans aucun mécanisme pour permettre aux composants intermédiaires d’intervenir.
Ce comportement court-circuite tous les efforts du concepteur de l’application pour
masquer ou résoudre le problème.
➤ La documentation des violations
Quand un de ces principes est violé, peut-être pour une bonne raison (par exemple,
une contrainte physique telle qu’une limitation de mémoire ou une séparation géographique qui forcent l’existence d’un pointeur), alors il faudra le documenter ! Toutes les
dépendances externes, tous les niveaux d’indirection, toutes les dépendances imprévisibles et toutes les décisions irrévocables doivent être documentés.
i
i
i
i
i
i
i
i
260
5
• La programmation avec état explicite
➤ Le moins possible de niveaux d’indirection
Cette règle est apparentée à la précédente. Quand A a un pointeur vers B, alors une
mise à jour de B exige une mise à jour de A. Toute indirection est une dépendance.
L’idée est d’éviter que le pointeur devienne détaché : sa destination n’a plus de sens
pour la source. Toute action sur B peut causer le détachement du pointeur de A. Le
pointeur de A n’est pas connu par B et il ne peut donc pas empêcher cela. Une solution
provisoire est de ne jamais changer B, mais uniquement d’en faire des copies modifiées.
Cela pourra être valable si le système fait de la gestion automatique de mémoire.
Deux exemples typiques des pointeurs problématiques sont des liens symboliques
dans un système de fichiers Unix et les URL. Les liens symboliques sont pernicieux
pour la maintenance d’un système. Ils sont commodes parce qu’ils peuvent référencer
d’autres arborescences montées dans un système de fichiers, mais en fait ils sont une
grande source de problèmes. Les URL sont connus pour être peu sûrs. Ils sont souvent
référencés dans les documents imprimés, mais leur durée de vie est généralement
beaucoup plus courte que celle du document. C’est parce qu’ils peuvent devenir
détachés rapidement mais aussi parce que l’Internet n’a pas une grande qualité de
service.
➤ Des dépendances prévisibles
Prenons par exemple la commande « localiser » qui garantit de récupérer un fichier
sur un réseau et d’en faire une copie locale. Son comportement est simple et prévisible,
ce qui n’est pas le cas pour la mémoire cache dans les navigateurs Web. Le terme
cache est mal choisi parce qu’une vraie mémoire cache maintient une cohérence entre
l’entité originale et la copie. Pour toute mémoire cache, la politique de remplacement
des pages doit être clairement indiquée.
➤ La prise des décisions au bon niveau
Une décision temporisée (« time out ») doit être prise au bon niveau. Il est faux
d’implémenter une décision temporisée de façon irrévocable à un bas niveau du
système (un composant fortement imbriqué), qui propage jusqu’au niveau le plus haut
sans aucun mécanisme pour permettre aux composants intermédiaires d’intervenir.
Ce comportement court-circuite tous les efforts du concepteur de l’application pour
masquer ou résoudre le problème.
➤ La documentation des violations
Quand un de ces principes est violé, peut-être pour une bonne raison (par exemple,
une contrainte physique telle qu’une limitation de mémoire ou une séparation géographique qui forcent l’existence d’un pointeur), alors il faudra le documenter ! Toutes les
dépendances externes, tous les niveaux d’indirection, toutes les dépendances imprévisibles et toutes les décisions irrévocables doivent être documentés.
