Patrón Money
Tags: softwarepatterns, softwaredesignpatter, cleancode, moneypattern
Published: 2023-09-28 13:23:59

---
title: Patrón Money
published: true
date: 2023-08-29 09:24:19 UTC
tags: softwarepatterns,softwaredesignpatter,cleancode,moneypattern
canonical_url: https://medium.com/all-you-need-is-clean-code/patr%C3%B3n-money-64989a3a6cf0
---

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

![](https://cdn-images-1.medium.com/max/1024/0*l-_ExGUeD2vo8xko)
_Photo by Jason Leung on Unsplash_

[**Artículo publicado originalmente para Secture&Code**](https://secture.com/blog/patron-money-maneja-correctamente-el-dinero/)

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_](https://amzn.to/3GhMvHD), 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_](https://dev.to/mangelsnc/value-objects-1gd9), 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:

![](https://cdn-images-1.medium.com/max/265/1*96rpkVsTvNI0Xy7iJDN8OA.png)
_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](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=maintenance-agency).

- **currency:** es el código [ISO-4217](https://en.wikipedia.org/wiki/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:

![](https://cdn-images-1.medium.com/max/1024/1*aMNb1aPtzhqadVsNCi88Sg.png)
_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:

![](https://cdn-images-1.medium.com/max/1024/1*NU-_VV6XKqq51D5FxmOMJA.png)

- **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:

![](https://cdn-images-1.medium.com/max/1024/1*geKh2oLrLUhKZTqY3Y87Eg.png)

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:

- **PHP:** [https://github.com/moneyphp/money](https://github.com/moneyphp/money)
- **Ruby:** [https://github.com/RubyMoney/money](https://github.com/RubyMoney/money)
- **Python:** [https://github.com/poswald/python-money](https://github.com/poswald/python-money)

#### 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

- [_Money Pattern._ **Martin Fowler**](https://martinfowler.com/eaaCatalog/money.html)
- [_Patterns of Enterprise Application Architecture._ **Martin Fowler (2002)**](https://amzn.to/3GhMvHD)
- [**Lista de unidades mínimas de cada moneda**](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=maintenance-agency)
- [**Lista de códigos ISO-4217**](https://en.wikipedia.org/wiki/ISO_4217)
- [_Money Pattern: The right way_](https://code.tutsplus.com/tutorials/money-pattern-the-right-way-to-represent-value-unit-pairs--net-35509)

* * *