Rules on working with money-related code


Every software engineer needs some basic rules in their head to ensure that the code will be written in time and the best way possible. A money-related code is no different. That is why I have put top-8 tricks on working with money-related code in one place. Enjoy.

  1. First of all: never use floating-point arithmetic for money calculations. You HAVE TO use BigDecimal instead. Why? Floating-point arithmetic usage leads to loss of precision.

([0.01] * 10).inject(:+) # => 0.09999999999999999
([0.01] * 10).map(&:to_d).inject(:+) # => 0.1e0
  1. Ensure that divider is a non-integer value. In Ruby, dividing integer value by integer value returns an integer result. One way to be confident in a result each time is to use to_d on a divider EVERY TIME.

nine, two = 9, 2
nine / two           # => 4
nine / two.to_d      # => 0.45e1
  1. Ensure that result value is non-negative (positive or zero) when you subtract one money value from another one. If application logic doesn’t allow such value, then it’s time to raise an exception. Otherwise, it’s possible to crop result value with .max.

one, two = 1, 2

!(one - two).negative? ? one - two : raise(StandardError)
# => StandardError

[one - two, 0.to_d].max # => # 0.0
  1. Money-related code HAS TO be covered with 100% coverage, mutant-testing is preferable.

  2. Money-related code HAS TO be isolated from any other services.

  3. Money-related code on frontend HAS TO be moved out of any components to a separate service with only money-related logic. Additionally it MUST be duplicated on backend to ensure that values from frontend are correct and match up.

  4. It’s possible to delegate money-related code to backed and call it via AJAX, but it’s still important to ensure received values correctness.

  5. Protect code from exceptional cases with exceptions

sum = 100.05.to_d
partitions = [0.5, 0.5]
parts = { |part| (sum * part).floor(2) }
raise(StandardError) unless parts.sum == sum

So here you are, the basic rules on working with money-related code. Have any ideas on which rules to add to this list? Be sure to share them in the comments section.