Split God Query Methods by Purpose
Replace universal dynamic queries with purpose-specific methods, migrate callers incrementally, and shrink the side-effect surface before deeper refactoring.
Source and AI note: This article is based on Gemini’s Devpractice on YouTube. It was generated and edited with the
gpt-5.6-solmodel.
Replace one universal dynamic query method with methods named for the purposes that call it. A method that accepts a large generic condition object and serves every workflow hides intent. Changing one branch exposes unrelated callers to side effects, especially when tests are absent.
Universal flexibility makes every change global
A repository method with many optional conditions looks reusable. Each caller supplies a different subset, and one implementation constructs all query variants. The apparent simplicity at the interface moves complexity into a long set of branches.
Later, a developer needs to change one workflow’s condition. The method name does not reveal which callers depend on that branch, and dynamic inputs make the combinations difficult to predict. A local requirement becomes a review of every call site.
A generic parameter object with many nullable fields worsens the problem. The caller’s purpose disappears behind values that happen to be present or absent.
Purpose-specific methods make intent inspectable
If a query supports account withdrawal, name an operation for that workflow and accept only the fields it needs. A join or registration flow should have a different operation if its conditions and reasons differ. The exact vocabulary follows the domain; the important change is that the method tells readers why the query exists.
Keep each purpose-specific method narrow instead of routing every query through one universal entry point.
Narrow the blast radius before improving internals
A heavily used legacy method should not be rewritten in one step. Pick one caller, copy the behavior it currently uses, and remove parameters that are always null for that path. Redirect that caller to the new method and deploy the separation.
At this stage, the copied query may remain unchanged. The first goal is to narrow the range affected by later edits. After the caller is separated, the smaller method can be cleaned up in another iteration.
Merge the refactoring while the system keeps moving
A long-lived branch gives teammates months to add more callers to the god method. Small, frequent merges change the default path sooner. Once one purpose-specific method exists, new work can use it while the next caller is migrated.
The objective is not to keep a complete rewrite on a private branch for months. Split one purpose, merge and deploy it, then continue with the next part. Purpose-specific methods keep every workflow from depending on the same universal switchboard.