0

So I have this issue with a website that I work on. It goes like so (note: This is not exactly what happens. I am just painting a picture):

Front-End:

  1. User has a cart full of things they want to buy
  2. Front-End calculates the amount that should be paid (this calculates in discounts, sales, Buy One Get One, etc.)
  3. User submits and pays the amount

Back-End:

  1. Items are bought and money is received
  2. Backend calculates a different amount for what everything should have cost
  3. Backend wants either less or more money

I think that I should calculate the amount in the same place. I think in step 2 I could make a call to the backend to determine what the amount should be.

That way I wouldn't run into this issue where they are calculating 2 different amounts. What do you guys think?

Slaknation
  • 2,124
  • 3
  • 23
  • 42

2 Answers2

1

If your frontend is implemented in JavaScript or some language that transcribes to JavaScript you should keep any business critical calculations (such as payment amounts) away from there. JavaScript logic is easy to manipulate in the browser and all critical code therefore needs to be executed in the backend server.

You should do exactly as you are suggesting and call your backend in step 2.

This will also make the system easier to maintain as you won't have duplicated logic in two places, any refactoring or debugging regarding this logic can be done in a single location in the codebase.

Johan Nordlinder
  • 1,672
  • 1
  • 13
  • 17
  • Frontend is actually done in Java. Does this change things? Someone I talked to said that it would take too long to do the call to the backend everytime we want to calculate the cart total. What do you think of that? – Slaknation Apr 06 '22 at 13:33
  • 1
    If your frontend calculations are already happening server-side that is good news as the security aspect is negated. But I still recommend you to go with option 2 if you can as it's a bad idea to spread out duplicated logic in the system. Too me it sounds strange that performance would be a bottleneck but I'm not familiar with your domain, are there large objects that needs to be passed around to do the calculation? If your backend system is also implemented in Java you could of course create a reusable calculation package that both frontend and backend can use. – Johan Nordlinder Apr 06 '22 at 13:42
  • 1
    Ok. Thanks Johan. I agree it should be sent to the backend. – Slaknation Apr 06 '22 at 13:51
0

This is probably a problem with rounding and floating numbers. The rounding functions and systems representing the numbers can be differently defined when different programming languages are used. Either you can use a library to use decimal numbers or try to implement the rounding behavior for one side to match the other side. Then it is always advised to calculate with integers as much as possible. Multiplying with 100 at the beginning and dividing with 100 at the end of calculations help to stabilize the numbers. Also, you should consider using bankers round also called Half Even rounding as a strategy when rounding currencies to minimize the total failure.

For TypeScript the function could be:

function roundHalfEven(x: number, d: number) {
  const p = Math.pow(10, d);
  const xp = x * p;
  const r = Math.round(xp);
  return (Math.abs(xp) % 1 == 0.5 && r % 2 != 0 ? r - 1 : r) / p;
}

The line const xp = x * p; could also be made more stable with const xp = parseFloat((x * p).toPrecision(15)).

But also do never trust anything coming from the browser. So you should definitely check at the end on your server if everything adds up.

You can find more information on rounding and how to handle failures on the following pages:

Good answer on this topic but be aware that everything should be taken with a grain of salt. For example the solution to Math.round(-0.5) is -0 and not -1 as in Amr Alis response.

ICU on rounding The most important rounding methods with sample data.

Florat
  • 119
  • 1
  • 7