8 votes

Devises/valeurs monétaires -- Comment les stocker dans une base de données et les transférer en utilisant JSON ?

Quelles sont les meilleures pratiques pour stocker des devises/valeurs monétaires dans la base de données, les traiter dans une application côté serveur, et enfin les envoyer au navigateur via une API JSON ?

J'ai imaginé deux approches, mais je ne sais pas comment peser le pour et le contre :

Stocker les valeurs sous forme d'entiers dans la plus petite unité monétaire.

  • En gros, cela signifie que la base de données stockera la valeur monétaire en cents / paises / shillings / etc.
  • L'application côté serveur fera correspondre cette valeur à une variable entière ordinaire.
  • L'API JSON représentera la valeur comme un nombre JSON normal.
  • L'inconvénient de cette approche est que vous devez constamment diviser par 100 avant d'afficher une valeur monétaire à l'utilisateur et toujours multiplier par 100 avant de stocker toute entrée utilisateur.
  • Problèmes possibles : Comment définir la plus petite unité monétaire ? Est-ce sur la base de deux ou quatre décimales ? Existe-t-il une monnaie qui n'a pas un rapport de 100:1, c'est-à-dire 100 cents = 1 dollar.

Stockez les valeurs sous forme décimale/numérique avec une précision et une échelle fixes.

  • La BD stocke la valeur monétaire comme un type décimal/numérique avec une précision et une échelle fixes, par exemple NUMERIC(10,2).
  • L'application côté serveur les fait correspondre à des objets spéciaux qui peuvent préserver la précision et l'échelle entre les calculs, par exemple. BigDecimal en Ruby.
  • L'API JSON échange ces valeurs comme cordes et non des chiffres. En effet, les nombres seraient automatiquement analysés comme des flottants par l'analyseur JSON, ce qui entraînerait une perte de précision.
  • L'inconvénient de cette approche est que tous les calculs côté serveur doivent s'effectuer dans un type de données encadré (éventuellement plus lent) ET que les analyseurs JSON doivent être conscients du fait que certaines chaînes ne sont pas réellement des chaînes, mais des valeurs numériques.
  • L'avantage de cette méthode est que vous n'avez pas besoin de multiplier et de diviser constamment par 100.

Existe-t-il une meilleure pratique généralement acceptée en la matière ?

4voto

Denis Points 34131

Les deux pratiques présentent deux autres écueils.

Tout d'abord, toutes les monnaies n'ont pas besoin de deux décimales. Beaucoup en ont besoin de trois. Beaucoup d'autres ont besoin de zéro. Et certaines applications spécifiques à un domaine, par exemple la finance et le forex, en nécessitent 5 ou 6.

Deuxièmement, certaines monnaies ont des taux de conversion colorés pour les sous-dénominations. Les anciennes roupies, par exemple, se convertissaient en 16 annas, 64 paises ou 192 pies. Heureusement, seuls deux pays conservent ce genre de taux de conversion farfelus si l'on en croit wikipedia : la Mauritanie où 1 ouguiya = 5 khoums, et Madagascar où 1 ariary = 5 iraimbilanja.

http://en.wikipedia.org/wiki/Decimalisation

Le fait est que vous ne devez pas être trop centré sur les États-Unis dans vos hypothèses si vous envisagez de localiser un jour votre application. Considérez au moins les cas d'utilisation où vous avez 0, 2 et 3 décimales, et réfléchissez un peu à la voie que vous voudriez suivre si vous deveniez international. Au cas où.

En passant, notez également que le numeric dans Postgres peut être stocké sans spécifier de précision. Cela ne prend pas plus de place, car il résidera tout de même dans le stockage étendu lorsqu'il sera trop grand. Et, tout comme varchar est meilleur que varchar(n) il sera plus rapide car vous éviterez la vérification de la précision intégrée lors du stockage de vos nombres (qui, dans ce cas, doivent être sains).

Quant à savoir laquelle des deux approches que vous décrivez est la meilleure, j'ai vu davantage la seconde - sous une forme simplifiée.

J'insiste sur trois points :

  1. Stocker la monnaie en tant que numeric avec ou sans précision, a du sens dans la BD, afin de ne pas introduire d'erreurs d'arrondi lors de la génération des comptes et des rapports. (Il existe également un type d'argent intégré, mais je ne l'ai jamais vu utilisé en pratique pour toutes sortes de raisons très valables).

  2. La vitesse devrait être le dernier de vos soucis si vous avez réellement besoin du type de précision qui dépasse un bigint ou un float à double précision (ce dernier est utilisé par js et json pour les nombres à virgule flottante, si ma mémoire est bonne). Si c'est votre cas, les mathématiques à précision arbitraire sont la voie à suivre, d'un bout à l'autre.

  3. Les applications typiques qui manipulent des montants monétaires typiques ne se heurteront jamais à ces limites de dépassement. Regardez bien. À moins que vous ne prévoyiez de stocker des montants en quadrillions de dollars américains, convertir des données numériques non limitées en chaînes de caractères et inversement pour les faire circuler dans json est un signe que vous avez trop développé votre application. Si c'est votre cas, contentez-vous des flottants en double précision et expédiez votre application.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X