Refactor the ownership of business logic, not the user’s entire workflow.
The issue was not another slow query. It was change risk: important calculations had accumulated across controllers, database views and helper methods.
The same finance rules were becoming harder to reason about because data retrieval and calculation were fused.
A mature CRM had accumulated financial values through database views and controller-level orchestration. A faster retrieval path risked creating a second implementation of the same business rules if calculations were simply copied into the new controller method.
The goal was therefore not merely “make a fast version.” It was to separate reusable calculations from the particular data-access path that happened to call them.
Make the calculation callable from both the legacy and optimized paths.
The important architectural move was to make the finance calculation independent from whichever query populated the input data.
public function getRecordFinance($recordId)
{
$row = DB::table('legacy_finance_view')
->where('record_id', $recordId)
->first();
// Retrieval and business calculations
// are coupled to this one path.
return [
'revenue' => $row->revenue,
'cost' => $row->cost,
'profit' => $row->revenue - $row->cost,
];
}
public function getOptimizedFinanceData($recordId)
{
$inputs = $this->loadFinanceInputs($recordId);
return $this->calculateFinance($inputs);
}
private function calculateFinance(array $inputs)
{
return [
'revenue' => $inputs['revenue'],
'cost' => $inputs['cost'],
'profit' => $inputs['revenue'] - $inputs['cost'],
];
}
Method names and domain identifiers are generalized, and the shown calculation body is simplified so proprietary finance rules are not published. The architectural point is that the new retrieval path did not need to invent a second business-rule implementation.
Preserve the contract while moving ownership underneath it.
Identified which calculations were already duplicated and which were merely called from multiple places.
Extracted reusable calculations rather than copying them into the new “fast” path.
Reduced reliance on database views where those views were acting as hidden business-logic containers.
Kept the existing caller contract so screens did not need a simultaneous rewrite.
Moved in small steps so old and new behavior could be compared during transition.
Left future changes with a clearer answer to “where does this rule belong?”
The visible workflow stayed familiar. The change surface underneath became much clearer.
Important calculations had a clearer application-level home.
Callers reused one implementation instead of reproducing the same decision.
The refactor targeted implementation structure rather than forcing a redesigned workflow.
Developers had fewer layers to inspect before changing an important rule.
This example is based on production PHP/Laravel refactoring work. Proprietary calculation details are simplified, while the architectural concern and extraction strategy reflect the real implementation work.