Balancing frontend interactivity and backend business logic in DDD

I’m new to Domain-Driven Design and I’m struggling with a problem in my sales order system. Here’s the issue:

Our system lets users input orders with multiple lines. Each line can have an amount in our base currency or a foreign one. If it’s foreign, we need to convert it using monthly exchange rates.

I know this conversion is a business rule and should be in the domain layer. But I also want the form to auto-calculate the base currency amount when users enter a foreign amount. This seems like it needs frontend logic, which goes against the ‘keep business rules out of the frontend’ principle.

How can I make this work? Is there a way to keep the form interactive without putting business logic in the frontend? Or am I thinking about this all wrong?

Here’s a basic example of what I’m trying to do:

function calculateBaseAmount(foreignAmount, exchangeRate) {
  // This feels like business logic in the frontend
  return foreignAmount * exchangeRate;
}

// Using it in a React component
const OrderLineForm = () => {
  const [foreignAmount, setForeignAmount] = useState(0);
  const [baseAmount, setBaseAmount] = useState(0);
  const exchangeRate = 1.2; // Simplified, would actually come from backend

  const handleForeignAmountChange = (e) => {
    const newForeignAmount = parseFloat(e.target.value);
    setForeignAmount(newForeignAmount);
    setBaseAmount(calculateBaseAmount(newForeignAmount, exchangeRate));
  };

  // Rest of the component...
}

Any advice would be really helpful!

hey mate, i’ve dealt with this before. one way to handle it is to make an API call to the backend for the conversion. that way, ur business logic stays on the server. you could use debouncing to avoid too many calls. it might add a bit of latency, but it keeps things clean. just my 2 cents!

Your approach to this challenge is commendable. One effective solution is to implement a thin client-side model that mirrors your domain model. This model can handle temporary calculations for user feedback, while the actual business logic remains server-side. When the form is submitted, the full validation and processing occur on the backend.

This method maintains the integrity of your domain-driven design while providing a responsive user interface. It’s a pragmatic compromise that many enterprise applications adopt. Remember, the goal is to keep core business logic centralized, not to completely eliminate all calculations from the frontend.

Consider also using TypeScript to ensure your client-side model accurately reflects your domain model’s structure and constraints. This can help prevent discrepancies between frontend and backend representations of your data.

hm, interesting issue! have u considered using a CQRS pattern? u could have a separate query model for the frontend that includes pre-calculated values. this way, ur keeping the core biz logic in the domain, but still providing quick data for the UI. what do u think about that approach?