Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

CoqBlog

.NET is good :-)
{ Blog de coq }

Actualités

Par pitié, quand nous stockons / transférons des données : pensons global

Par "global", j'entend bien "ayant la même signification quelle que soit la culture de l'utilisateur".
Souvenez-vous de la dernière fois où vous avez dû incorporer dans votre process le traitement d'un fichier "texte" (XML ou autre) dont les données étaient enregistrées de façon sensible à la culture... Mais si, vous savez, c'est en général aussi le type de fichier dont le format a tendance à changer du jour au lendemain sans crier gare.

Pour moi l'affichage de l'information suivant les paramètres régionaux de l'utilisateur n'est justement qu'un problème de rendu : le stockage des données et les formats de transfert doivent absolument être neutres.
Et c'est de plus en plus important : à l'heure du tout connecté, nous ne pouvons plus vraiment compter sur l'utilisation d'une application au sein d'une seule culture.

Il y a probablement des cas particuliers où un stockage sensible à la culture serait requis, mais je pense qu'à chaque fois que c'est possible il faut faire le maximum pour s'affranchir de la culture de l'utilisateur.

 

Le problème

Lorsqu'un transfert de données doit s'effectuer au moyen d'un format texte (XML, CSV, ...), on peut être tenté de présenter les données de façon à ce qu'elles puissent être aisément lues à l'oeil nu.
A mon avis il s'agit d'une erreur, pouvant avoir des conséquences plus ou moins graves à court ou moyen terme.

Pour illustrer le problème, prenons un cas très simple (et qui peut donc paraitre un peu idiot) : une application de prise de notes, initialement développée par un Français.
Les données stockées sont la date/heure de saisie, et le texte. Le stockage est effectué sous forme d'un fichier XML, sans schéma fixant de manière stricte le format et les types. Le rendu de la date sous forme de chaîne de caractères est effectué via la méthode ToString standard, sans paramètre : le rendu est donc sensible à la culture de l'utilisateur exécutant le code (pour simplifier).

Utilisée avec des paramètres régionaux "Français (France)" (fr-FR) standards, le fichier produit par l'application a l'aspect suivant :

image

Jusqu'ici, rien de bien choquant. Cependant, notre développeur se fait quelques amis, auxquels il donne son application :

un Belge utilisant des paramètres fr-BE
image

un Canadien (fr-CA)
image

un Américain (en-US)
image

un autre Canadien (en-CA)
image

un Anglais (en-GB)
image

et un Russe (ru-RU)
image

Nous constatons une nette différence de formatage de la date entre les différentes cultures, ce qui ne posera pas de problème à l'utilisateur tant qu'il ne changera pas ses paramètres régionaux : à la lecture la même culture sera utilisée pour faire la transformation inverse.

Mais que va-t-il se passer si ces personnes désirent s'échanger leurs notes ? Au mieux une erreur, au pire une corruption de données comme c'est par exemple possible sur la Note 2 entre les cultures en-US et en-CA : le deux décembre de l'un deviendra simplement le douze février de l'autre.

Ce format n'est même pas viable en local : le même problème de corruption se posera pour l'utilisateur Canadien (en-CA) s'il vient à changer ses paramètres régionaux pour du en-US (et vice-versa).

 

Les solutions qui auraient pu fonctionner

Une solution serait de persister l'information de culture dans l'entrée, et de l'utiliser au moment de la lecture.
Mais cette solution n'est pas viable à 100% parce que rien ne nous assure que la personne n'ait pas effectué une personnalisation de ses paramètres régionaux.
Par exemple, un français dont les paramètres sont basés sur la culture fr-FR a horreur du format de date "dd/MM/yyyy", et lui préfère le format "yyyy.MM.dd" pour le pattern de date courte. Comme il peut le faire, il a donc modifié ses paramètres régionaux et son enregistrement aura cet aspect là : 
image 

La persistance de l'information fr-FR n'est donc pas suffisante, et enregistrer les chaines de format (dans le cas présent, DateTimeFormatInfo.ShortDatePattern et DateTimeFormatInfo.LongTimePattern de la culture courante) deviendrait vraiment trop contraignant.

Une autre solution serait d'imposer l'utilisation d'une seule et même culture à tout le monde. Le choix risque de se porter soit par réflexe sur de l'en-US, soit sur la culture d'origine de la solution.
Mais cela risque de poser problème, surtout en termes d'interopérabilité avec d'autres solutions, mais aussi sur le côté humain des choses : chacun aura une tendance naturelle à préférer sa culture.

 

La solution générale

La seule solution générale que je connaisse est d'utiliser la culture dite "indifférente" : on reste dans l'imposition d'utilisation d'une culture, mais elle est considérée comme neutre et donc évite les problèmes entres humains qui voudraient imposer leur propre culture.

Pour cela il suffit, partout où c'est possible, de spécifier de manière explicite les paramètres de culture.
C'est généralement possible directement sur les méthodes produisant une chaine de caractères, et qui possèdent un paramètre typé IFormatProvider (les classes CultureInfo, DateTimeFormatInfo et NumberFormatInfo sont des implémentations de cette interface).

image

 

La solution dans le cas particulier d'XML

Dans le cas de l'émission d'un flux XML, le plus simple est encore d'émettre les chaines de caractères en suivant partout où c'est possible les règles spécifiées pour les types de données définis par XSD (XML Schema Part 2: Datatypes Second Edition).
Ceci ne nous oblige pas à définir un schéma XSD pour le flux, même si ça serait du coup pratique pour la validation et la communication à des tiers.

En .NET ceci se fait très simplement :

  • par utilisation, lors de l'émission de XML via XmlWriter, de la méthode WriteValue dont les différentes surcharges permettent de traiter les types Boolean, DateTime, Decimal, Double, Int32, Int64 et Single.
    Des types supplémentaires sont pris en charge par WriteValue(Object), par exemple : Byte, Byte[], DateTimeOffset, Int16, SByte, TimeSpan, UInt16, UInt32 et UInt64
  • à défaut, par utilisation de la classe XmlConvert qui expose, entre autres, une méthode ToString dont les surcharges permettent de traiter les types : Boolean, Byte, Char, DateTime, DateTimeOffset, Decimal, Double, Guid, Int16, Int32, Int64, SByte, Single, TimeSpan, UInt16, UInt32 et UInt64

 

 

Si vous avez d'autres suggestions ou des exemples de cas où ce que j'ai exprimé dans cet article ne convient pas, n'hésitez pas à laisser un commentaire.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: samedi 12 juin 2010 21:01 par coq
Classé sous : , ,

Commentaires

Renfield a dit :

Je plussoie forcement, je milite pour le meme chose depuis des annees...

# juin 13, 2010 06:52

KooKiz a dit :

Je ne connaissais pas XmlConvert pour générer une valeur indépendante de la culture. Je ne manquerai pas de l'utiliser à l'avenir :)

# juin 14, 2010 09:44

JeremyJeanson a dit :

Bon poste de sensibilisationà la localisation ;)

perso je suis un grand fan de CultureInfo.InvariantCulture

# juin 14, 2010 09:51

JeremyJeanson a dit :

...CultureInfo.InvariantCulture pour la globalisation il vas s'en dire ;)

# juin 14, 2010 09:51

coq a dit :

@KooKiz : en fait XmlConvert c'est surtout pour émettre les données conformément à XSD, pas forcément juste pour faire de l'insensible à la culture :-)

# juin 14, 2010 12:18
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01