DEV Community

Miguel Ángel Sánchez Chordi
Miguel Ángel Sánchez Chordi

Posted on • Originally published at Medium on

Patrón Money

Maneja correctamente el dinero en tu aplicación y prepárala para el escalado internacional


Photo by Jason Leung on Unsplash

Artículo publicado originalmente para Secture&Code

Trabajar con cantidades de dinero nunca ha sido un asunto sencillo: redondeos, cambios de divisa… una mala gestión puede derivar en perdidas para nuestra empresa o en cobrar de más a nuestros clientes, con el consiguiente perjuicio reputacional.

El patrón Money

Martin Fowler publicó en 2002 su famoso libro Patterns of Enterprise Application Architecture, donde uno de los patrones incluidos era el llamado patron Money. Con este patrón, Fowler pretende simplificar la gestión de cantidades monetarias y reducir los posibles riesgos que antes comentábamos.

El patrón Money se basa en otro patrón conocido como Value Object, y consiste en modelar un pequeño objeto que represente una cantidad monetaria. Para ello se usan dos atributos: la cantidad (amount), y la moneda (currency), y una serie de operaciones lógicas y matemáticas:


Diagrama UML del Patrón Money

Atributos

  • amount: es el importe, representado siempre en la unidad mínima de la moneda asociada. Esta representación es perfecta para realizar comparaciones entre cantidades de una misma moneda, ya que las comparaciones entre números en coma flotante siguen siendo un asunto sin resolver en cualquier lenguaje.

Es importante saber que no todas las monedas son como el dólar o el euro, ya que no en todas la unidad mínima es el céntimo. Existen monedas donde la propia moneda es la unidad mínima, y otras donde no sólo tienen céntimos, sino que tienen unidades más pequeñas que el céntimo.

Ejemplos de estos casos son el dinar de Bahrain, con milésimas partes del dinar, o el peso de Chile, donde no hay unidades inferiores al peso.

Podemos consultar una lista con todas las monedas este enlace.

  • currency: es el código ISO-4217 de la moneda con la que estamos trabajando. Es un código de 3 letras que representa la moneda de forma internacional, por ejemplo EUR para Euros.

Métodos / Operaciones

  • +, -, *, / : operaciones matemáticas básicas, como la suma, resta, multiplicación, división…
  • allocate: una operación especial destinada a dividir una cantidad de dinero entre dos o más receptores. Luego entraremos más en detalle.
  • *<, >, ≤, ≥, = * : operaciones lógicas básicas, como menor que, mayor que, menor igual que, mayor igual que, igual

Ejemplos

Queremos representar la cantidad 528.75€, cuya unidad mínima es el céntimo de euro:

  • amount: 52875
  • currency: EUR

Queremos representar la cantidad 528.75.د (dinares de Bahrain), cuya unidad mínima es la milésima parte de un dinar.

  • amount: 528750
  • currency: BHD

Para representar visualmente la cantidad, solo necesitamos aplicar la sencilla fórmula: amount / (10 x unidad mínima).

Implementación

Es sencillo realizar una implementación básica de este patrón, lo realmente tedioso es tener actualizada siempre la lista de monedas, con sus unidades mínimas o sus ratios de conversión.

Veamos una implementación sencilla en PHP:


Patrón Money básico en PHP

A esta implementación básica le faltarían todos los métodos de las operaciones lógicas y matemáticas. He querido dejar de lado esta implementación para poder comentar que podemos hacerlo en dos versiones distintas:

  • Orientado a objetos: añadiendo los métodos add, substract, multiply, divide… Este sería el estilo orientado a objetos clásico. Nos permitiría tomar dos enfoques: mutable (modifica la instancia actual) o inmutable (no modifica la instancia, devuelve una nueva). De esta manera podremos ejecutar cosas como:

  • Sobrecarga de operadores: muchos lenguajes orientados a objetos, como Java, PHP, Python o Ruby permiten lo que llamamos sobrecarga de operadores, que no es más que permitir cambiar el comportamiento de los operadores aritméticos y lógicos cuando estos son aplicados a objetos de cierta clase, y no a tipos primitivos como se hace habitualmente. Esto nos permitiría sobrecargar los operadores de tal manera que podríamos ejecutar algo así como:

La implementación básica de este patrón es realmente muy sencilla, pero si queremos sacarle el máximo provecho tenemos implementaciones en casi todos los lenguajes, que además cubren otros aspectos como la representación visual de la cantidad (situar el símbolo monetario a la derecha o a la izquierda), o la conversión entre divisas.

Algunas implementaciones conocidas:

Método allocate

Este método, como ya comentamos antes, es un método especial usado para distribuir adecuadamente una cantidad entre dos o mas receptores cuando no puede hacerse de forma exacta (sin sobras). Por ejemplo cuando lo hacemos basándonos en porcentajes o ratios.

Veamos un caso específico:

Queremos repartir 5cts de euro entre dos cuentas al 30%-70%. Esto implica un reparto de 1,5cts y 3,5cts. El problema es que el céntimo es la unidad mínima de la divisa euro, y no podemos partir un céntimo en dos, por lo tanto el reparto exacto no puede hacerse.

La solución más habitual es repartir 1 céntimo a cada recipiente mientras no hayan llegado a la cantidad justa. Una vez haya sobrepasado esa cantidad, deja de recibir dinero.

Recipiente A: 1.5cts

Recipiente B: 2.5cts

  1. Recipiente A: 1cts (1 < 1.5 ✅). Recipiente B: 1cts (1 < 2.5 ✅)
  2. Recipiente A: 2cts (2 < 1.5 ❌). Recipiente B: 2cts (2 < 2.5 ✅)
  3. Recipiente B: 3cts (3 < 2.5 ❌)

Recipiente A: 2cts

Recipiente B: 3cts

Bibliografia


Top comments (1)

Collapse
 
wilson124607 profile image
ew2323219

¡Es genial que estés interesado en aprender a jugar en casinos en línea! Comenzar puede parecer abrumador al principio, pero con la orientación adecuada, pronto estarás disfrutando de la emoción de los juegos en línea. Una vez que hayas seleccionado un casino, el siguiente paso es registrarte para obtener una cuenta. Visita el sitio del casino en línea bono sin depósito casino méxico y sigue los pasos para completar el proceso de registro. Asegúrate de proporcionar información precisa y verificable.