O Que é um Ledger e Por Que Pontos Flutuantes Não São Recomendados?
No contexto de transações financeiras e ledgers, a precisão é fundamental. No entanto, usar números de ponto flutuante para representar valores monetários pode levar a problemas significativos.
O que é Ledger Série
No contexto de transações financeiras e ledgers, a precisão é fundamental. No entanto, usar números de ponto flutuante para representar valores monetários pode levar a problemas significativos devido à sua imprecisão inerente. É por isso que é crucial entender os problemas com pontos flutuantes e considerar abordagens alternativas.
Por Que Pontos Flutuantes São Problemáticos
Os números de ponto flutuante são uma maneira comum de representar números reais na computação. No entanto, eles não são adequados para cálculos financeiros precisos devido a erros de arredondamento. Aqui estão alguns exemplos que ilustram o problema:
console.log(0.1 + 0.2); // Esperado: 0.3, Real: 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // Esperado: true, Real: false
Essas pequenas imprecisões podem se acumular em muitas transações, levando a erros significativos nos registros financeiros.
Usando Centavos ou Decimal128
Para evitar esses problemas, é recomendado representar valores monetários nas menores unidades (como centavos) ou usar um tipo de dado projetado para alta precisão, como Decimal128
no MongoDB. Isso garante que todos os cálculos sejam exatos, mantendo a integridade dos dados financeiros.
Atualizando o Exemplo para Usar Centavos
Vamos atualizar nosso exemplo anterior para armazenar valores em centavos em vez de dólares, garantindo a precisão em nossos cálculos.
Defina a estrutura do ledger no MongoDB usando centavos:
{
_id: ObjectId("60c72b2f9b1d8e4d2f507d3a"),
date: ISODate("2023-06-13T12:00:00Z"),
description: "Depósito",
amount: 100000, // Valor em centavos
balance: 100000, // Saldo em centavos
transactionId: "abc123"
}
Função para adicionar uma nova entrada ao ledger e calcular o saldo usando centavos:
const { MongoClient } = require('mongodb');
async function addTransaction(description, amount, transactionId) {
const url = 'mongodb://localhost:27017';
const client = new MongoClient(url);
try {
await client.connect();
const database = client.db('finance');
const ledger = database.collection('ledger');
const existingTransaction = await ledger.findOne({ transactionId: transactionId });
if (existingTransaction) {
console.log('A transação já existe:', existingTransaction);
return;
}
const lastEntry = await ledger.find().sort({ date: -1 }).limit(1).toArray();
const lastBalance = lastEntry.length > 0 ? lastEntry[0].balance : 0;
const newBalance = lastBalance + amount;
const newEntry = {
date: new Date(),
description: description,
amount,
balance,
transactionId: transactionId
};
await ledger.insertOne(newEntry);
console.log('Transação adicionada com sucesso:', newEntry);
} finally {
await client.close();
}
}
addTransaction('Depósito', 50000, 'unique-transaction-id-001'); // Valor em centavos
Claro, se você estiver fazendo uma alteração como esta, será necessária uma migração do banco de dados. Com o mongo, isso é mais fácil. Você pode verificar como lidamos com isso em nosso artigo Zero Downtime Database Migrations at Woovi
O objetivo aqui é mostrar o que você pode aprender com erros comuns.
APIs da Woovi Utilizam Centavos
A Woovi, uma plataforma moderna de serviços financeiros, utiliza centavos em suas APIs para garantir precisão e evitar os problemas da aritmética de ponto flutuante. Ao fazer isso, nós mantemos a precisão e a confiabilidade das transações financeiras, o que é crucial tanto para suas operações quanto para a confiança dos seus clientes.
Conclusão
Implementar a idempotência no seu sistema de ledger é crucial para manter registros financeiros precisos e confiáveis. Ao garantir que cada transação seja registrada apenas uma vez, você pode evitar entradas duplicadas e manter a integridade dos seus dados.
Como vimos, a idempotência não é apenas um detalhe técnico, mas um princípio fundamental que ajuda a construir sistemas robustos e tolerantes a falhas. Da mesma forma, usar centavos em vez de pontos flutuantes garante cálculos financeiros precisos. No nosso próximo post, exploraremos tópicos mais avançados em gerenciamento de ledgers e como lidar com outros desafios, como concorrência e consistência eventual.
Fiquem atentos para mais insights sobre a construção de sistemas financeiros confiáveis!
Sigam-me no Twitter
Se gosta e quer apoiar o meu trabalho seja meu patreon
Quer alavancar sua carreira? Comece agora com minha mentoria pelo link
https://mentor.daniloassis.dev
Veja mais em https://linktr.ee/daniloab
Photo of Andrew Spencer in Unsplash