How to Prevent AQC Classes from Becoming Too Large
Muhammad Raheel
March 27th, 2026 · 4 min read
Atomic Query Construction (AQC) classes are supposed to encapsulate one specific action—like fetching users, orders, or products. That’s the single responsibility principle in practice: the class name should clearly tell the world what it does. But a single action can still require multiple filters, joins, and conditional logic. The key is not to avoid complexity, but to organize it internally so the class remains readable and maintainable.
Here’s how to do it right.
1. Define Only the Necessary Filters
Your AQC class should include all the filters and joins it actually uses, not every theoretical filter that could exist. If your table has 20 columns, don’t create 20 conditional filters. Only define filters that the application frequently uses.
This ensures your class:
- Covers all real scenarios
- Doesn’t waste time on imaginary use cases
- Remains concise despite handling multiple conditions
2. Split Logic Into Internal Methods
Even when a class handles many combinations of filters and joins, you can prevent it from looking like a giant blob by splitting the logic into internal methods.
Example:
This keeps the public interface clean, while internal methods organize complexity.
3. Compose Queries in a Flexible Way
AQC classes should compose the query using all applicable filters and joins. The key difference from naive designs is that each combination is defined only when required. This ensures that:
- The class represents all practical combinations
- It stays predictable and reusable
- Adding a new filter doesn’t require rewriting the entire class
4. Name Classes to Reflect One Action
Even if a class handles many filters internally, the class name should clearly communicate its purpose. This is the external single responsibility principle: everyone reading the code should understand what action the class performs without worrying about the internal complexity.
Example:
GetUsersUserQueryAQC
5. Avoid Unused or Rarely Used Filters
Don’t predefine filters that aren’t used in practice. This keeps the class focused on the combinations your application actually needs, which is far more valuable than trying to anticipate every hypothetical scenario.
6. Internal Organization Beats Class Splitting
Unlike traditional advice about splitting everything into multiple classes, your goal here is clarity through internal methods, not fragmentation. A single well-organized class is better than five classes that are conceptually the same but split for no good reason.
Final Thoughts
Preventing AQC classes from becoming “too large” isn’t about limiting combinations or avoiding complexity. It’s about:
- Keeping a single, clear purpose
- Defining only the filters and joins you actually need
- Organizing the logic into internal methods
- Naming the class to reflect its one action
When done right, an AQC class becomes a powerful, reusable tool that handles every real scenario for its action without turning into an unreadable mess.