Blog #32: Friday Afternoon, 800 Lines of Code, and a Miscalculation
When mixing business logic into a UI component turns bug fixing into a multi-hour nightmare.
It's 4:30 PM on a Friday. I'm packing up to head home when an urgent ticket comes in: "Customers are being charged the wrong order value when applying 2 discount codes at once." I open the OrderSummary.tsx file. 800 lines of code appear before my eyes.
The JSX display section is tightly interwoven with map, filter functions, and logic for calculating percentages, taxes, and shipping fees. Reading the code feels suffocating. Business logic is "whispering" right alongside <div> and <button> tags.
Initially, I blamed the backend: "Surely the API returned the wrong value." But checking the Network tab, the data was perfectly accurate. The fault was mine. On line 452, an if/else condition was written backwards, causing shipping fees to be added instead of deducted.
1. What happened?
A simple logic error became extremely difficult to find because it was buried deep within an oversized UI component. The lack of Separation of Concerns turned this file into a "Big Ball of Mud."
2. What I thought the cause was
I assumed it was because data from the API wasn't formatted with the correct type (string vs number). I spent time writing Number() wrappers all over the place to force types, but it still didn't solve the problem.
3. How I debugged it
Since I couldn't quickly write Unit Tests for this logic (due to it being coupled with the UI), I had to use console.log at every calculation step. Each time I checked the result, I had to wait for Webpack's hot-reload and interact with the UI to trigger the logic.
4. The moment of realization
I realized I was lost in a maze of my own making. Why did I let a UI component be responsible for calculating a complex financial problem? If this logic had been in a separate function, I could have caught the error immediately with a simple test suite.
5. The fix
- Quick patch: Fix the incorrect
if/elsecondition to make the release. - Real fix: Extract all calculation logic into Pure Functions within the
utilsorservicesdirectory. The UI should have a single responsibility: Receive data and display it.
6. Looking back
I was too lazy, thinking that "writing it together is faster." Mixing UI and Logic is the quickest way to turn a project into "legacy code" after just a few weeks of development. If I were designing it again, I would mandate that all calculation logic be unit tested independently before being brought into a component.
Series • Part 32 of 50