notes-fr
# -*- encoding: utf-8; indent-tabs-mode: nil -*-
Notes du concepteur
Préliminaire
Ce texte détaille les notes de conception pour le module de calendrier hébraïque. Une version complète figure dans la distribution Perl 6 pour le module de calendrier républicain.
Il est préférable de faire référence à des exemples plutôt que d'utiliser des données génériques. Pour ce faire, j'utiliserai les dates suivantes (le 14 juillet de cette année) :
Dimanche 14 juillet 2019
Sunday 14 July 2019
11 Tammuz 5779
11 Dhu al-Qada 1440
Sextidi 26 Messidor 227
13.0.6.11.16, 8 Cib, 4 Xul
Buts
Les modules de calendrier doivent tendre vers ces buts contradictoires :
Un utilisateur peut décider de charger autant de modules qu'il souhaite. Il peut tous les utiliser ou n'utiliser aucun module outre le module central
Date.Limiter autant que possible la duplication de code. Plutôt DRY (Don't Repeat Yourself, Ne vous répétez pas) que WET (Write Everything Twice, Tout écrire deux fois).
Ne pas toucher aux modules standards, y compris
Date.
Première idée : des rôles partout
Ma première idée était d'utiliser de manière intensive la nouveauté
de Perl 6 en programmation objet, les rôles. Seul le calendrier grégorien
serait implémenté en tant que classe, les autres calendriers seraient
des rôles accolés à la classe Date. Par exemple :
my Date $quatorze-juillet does Date::Calendar::Hebrew
does Date::Calendar::Hijri
does Date::Calendar::FrenchRevolutionary
does Date::Calendar::Mayan
.= new(year => 2019, month => 7, day => 14);
Le premier problème est le conflit de nom entre les méthodes des divers rôles. Si nous codons :
say $quatorze-juillet.month-name
obtiendrons-nous Tammuz, Dhu al-Qada ou Messidor ?
D'accord, il suffit de lire la page 226 et les suivantes de
Learning Perl 6 et l'on apprend que l'on peut écrire :
say $quatorze-juillet.month-name( Date::Calendar::FrenchRevolutionary );
# → Messidor
say $quatorze-juillet.month-name( Date::Calendar::Hebrew );
# → Tammuz
Mais c'est laborieux.
Le second problème est que le concept de date n'est pas le même d'une civilisation à l'autre. Le calendrier grégorien et le calendrier républicain utilisent des dates de minuit à minuit, alors que le calendrier hébraïque, le calendrier islamique et plusieurs autres utilisent des dates du coucher du soleil au coucher suivant. Le Julian Day Number (à ne pas confondre avec le calendrier julien) se base sur des dates de midi à midi. Et il n'est pas exclu que d'autres calendriers définissent les dates comme s'étendant du lever du soleil au lever suivant du soleil. On peut donc assimiler le 14 juillet 2019 au 26 Messidor 227, mais pas au 11 Tammuz 5579. Habituellement, les programmes de conversion s'en tirent en écrivant dans la documentation utilisateur que la conversion 14 juillet 2019 → 11 Tammuz 5779 est valide avant le coucher du soleil. Mais il pourrait y avoir un programmeur un peu plus aventureux qui coderait deux routines de conversion ou qui ajouterait un paramètre « moment de la journée » à sa routine de conversion pour obtenir soit :
14 juillet 2019 → 11 Tammuz 5779
soit :
14 juillet 2019 → 12 Tammuz 5779
En implémentant le calendrier hébraïque en tant que rôle affecté au calendrier grégorien, cette possibilité n'existerait plus. En implémentant le calendrier hébraïque en tant que classe séparée, la possibilité reste ouverte. Il reste des problèmes à résoudre dans ce cas, mais au moins nous ne sommes pas bloqués.
Pendant que j'écrivais le module de calendrier républicain, j'ai trouvé un argument supplémentaire. L'utilisation d'années négatives (ou av J.C.) est justifiée pour le calendrier julien et le calendrier grégorien (même en considérant que le calendrier grégorien a pris effet le 15 octobre 1582), ce n'est pas le cas pour les autres calendriers. Ainsi, le calendrier républicain a pour origine des temps le 22 septembre 1792 et il n'y a alors aucune raison d'autoriser l'objet 21 septembre 1792 à utiliser les méthodes du rôle « calendrier républicain ».
La solution est donc : un calendrier = une classe.
Examen du module standard Date
Je n'avais pas l'intention de traiter les heures (décimales ou
24×60×60) donc j'ai seulement regardé Date, pas DateTime.
Échelle de temps en jours
La première différence entre le module Date de Perl 6 et le module
DateTime de Perl 5 est que Perl 6 utilise le MJD (Modified Julian
Day Number) au lieu d'utiliser le Rata Die. Cela me va très bien.
Immutabilité
Une deuxième différence avec le module DateTime de Perl 5, c'est
que les dates ne sont pas modifiables. Et pourquoi pas ? Cela ne me
dérange pas. Donc les dates dans Date::Calendar::xxx ne seront
pas modifiables. Voir cependant ci-dessous le cas d'un calendrier avec
plusieurs langues.
Affichage en langage naturel
Une autre différence avec Perl 5, c'est qu'il n'y a rien de prévu en
standard pour afficher du langage naturel, essentiellement les noms
des jours et les noms des mois. Peut-être a-t-on estimé que
l'utilisation principale du module Date serait la constitution
d'horaires ou la planification de tâches, ce qui ne nécessite que les
valeurs numériques des jours et des mois, pas les noms en clair.
Et si vous avez quand même besoin des noms en clair, vous pouvez
installer et utiliser Date::Names disponible sur zef ou CPAN6.
Calendrier simple
Comme exemple de calendrier simple, je prendrai le calendrier hébraïque. La simplicité concerne l'architecture du module, pas les algorithmes de conversion. Il n'y a pas de variante pour le calendrier hébraïque, donc de ce point de vue c'est un calendrier simple.
Calendrier avec une seule langue
À mon avis, si quelqu'un utilise un module de calendrier autre que
grégorien, c'est pour afficher la date convertie, pas pour faire des
calculs de délai ou planifier des tâches. Les noms en clair seront
dans un module séparé, mais ce module séparé fera partie intégrante de
la distribution. Ainsi, la distribution Date::Calendar::Hebrew
incluera à la fois le module Date::Calendar::Hebrew et le module
Date::Calendar::Hebrew::Names.
En résumé, nous avons dans ce cas :
classe Date::Calendar::Hebrew
routines Date::Calendar::Hebrew::Names
Calendrier avec plusieurs langues
Si les noms sont disponibles dans plusieurs langages pour un même
calendrier, je peux dans certains cas tout mettre dans un même module
Date::Calendar::xxx::Names, mécanisme et données, ou bien je peux
scinder cela en mettant le mécanisme dans
Date::Calendar::xxx::Names et les données dans
Date::Calendar::xxx::Names::en, Date::Calendar::xxx::Names::fr,
Date::Calendar::xxx::Names::it et ainsi de suite. Tout dépendra
de la taille.
Pour le calendrier hébraïque, avec l'hébreu, le yiddish et l'araméen, cela donnerait :
classe Date::Calendar::Hebrew
routines Date::Calendar::Hebrew::Names
routines Date::Calendar::Hebrew::Names::he
routines Date::Calendar::Hebrew::Names::yi
routines Date::Calendar::Hebrew::Names::arc
(Désolé, l'araméen n'a pas de code ISO 639 à deux caractères, j'ai dû me rabattre sur le code à trois caractères.)
Un autre point est que dans le cas où plusieurs langages sont
disponibles, l'objet Date::Calendar::xxx aura un attribut
locale et l'utilisateur pourra alors faire varier cet attribut pour
afficher une même date dans plusieurs langues. Même si les attributs
année, mois et jour sont invariants, l'attribut locale sera
modifiable. Et l'objet ne sera plus totalement « immutable ». En
prenant un exemple tiré du calendrier républicain, changer « Sextidi
26 Messidor 227, jour de la sauge » en « Sixday 26 Reapidor 227, day
of sage » est une modification cosmétique et superficielle de
l'instance de date, changer « Sextidi 26 Messidor 227 , jour de la
sauge» en « Septidi 27 Messidor 227, jour de l'ail » est une
modification profonde et essentielle de l'instance.
Calendriers avec variantes
Dans le but de rester simple, le présent texte n'ira pas plus loin
et laissera de côté le cas plus compliqué des calendriers avec
variantes. Veuillez vous référer à la distribution
Date::Calendar::FrenchRevolutionary qui contient la version
complète du présent texte.
Licence
Texte diffusé sous la licence CC-BY-SA : Creative Commons avec attribution, partage dans les mêmes conditions.