Why Good Systems Start With Shape, Not Speed
Hatched by Kai Nguyen
Jun 12, 2026
10 min read
1 views
78%
The Hidden Connection Between a Fast Query and a Maintainable Class
What do a slow SQL query and a messy object model have in common? More than most engineers realize: both usually fail because they ask the system to do work at the wrong time, in the wrong place, with the wrong shape.
That is the deeper tension running through both database optimization and object oriented design. We tend to think performance problems are about horsepower, and design problems are about elegance. But the real issue is often structural. A query becomes slow when it forces the database to inspect too much data, too late. A class becomes painful when it forces every instance to carry responsibilities that should have been separated, shared, or delegated.
In both cases, the highest leverage move is not to work harder inside the system. It is to reshape the problem so the system can do less work.
Good design is not just about expressing intent clearly. It is about making the easy path for the machine also the right path for the human.
That principle connects index friendly SQL, instance attributes, class attributes, inheritance, and even the humble __str__ method. They are all examples of one broader idea: structure determines cost.
Performance Is Mostly a Question of Shape
SQL optimization often feels like an arcane art, but the core lesson is surprisingly simple: if the database can reason about your request using its existing structure, it can respond quickly. If your query obscures that structure, the engine has to work much harder. That is why a SARGable condition matters, why leading wildcards are expensive, and why arithmetic on indexed columns can ruin index usage.
The database is not being stubborn. It is being literal. An index is useful because it narrows search. But when you wrap the indexed column in a function, negate it, or transform it inside the WHERE clause, you ask the engine to inspect the transformed values instead of the stored order. In effect, you have hidden the map.
This same pattern shows up in code organization. A class is a blueprint, while an instance carries real data. When responsibilities are bundled well, the program can locate behavior quickly because the shape of the code mirrors the shape of the problem. When everything is mixed together, the programmer becomes the query planner, manually hunting for meaning across tangled logic.
Think of a library. A well organized library does not necessarily contain fewer books. It simply makes retrieval cheap. Indexes, classes, attributes, and methods all exist to reduce search cost. They make one thing obvious: clarity is a kind of optimization.
A useful mental model here is to ask:
- What does the system already know how to find efficiently?
- What am I doing that forces it to rediscover that information?
- Can I rephrase the request or redesign the object so the answer emerges directly?
That is true whether the system is a database engine or a Python codebase.
The Real Cost of Transforming Data Too Late
One of the most revealing rules in SQL is to filter early with the WHERE clause. It sounds obvious, but it expresses a profound design principle: the earlier you reduce the problem, the less work everything downstream must do.
If you wait until after sorting, grouping, or calculating to eliminate irrelevant rows, you pay for operations on data you never needed in the first place. That is not just inefficient. It is a sign that your mental model of the task is inverted.
The same mistake appears in object oriented design when we place mutable state or behavior at the wrong level. An instance attribute belongs to one object. A class attribute belongs to all objects of that class. If a property is shared but stored separately in every instance, we create unnecessary duplication. If a property varies by instance but is stored at the class level, we create confusion and bugs.
That distinction is not merely about memory. It is about where truth lives.
Imagine a fleet of delivery drones. Their battery capacity might be a class attribute if all models share the same specification. But current location, remaining charge, and assigned route are instance attributes, because they differ from drone to drone. If you blur those categories, you force the system to do constant reconciliation. Every action becomes a correction of a prior modeling error.
SQL and OOP both punish late correction. In SQL, if you wait until after a join or sort to reduce rows, you pay an inflated cost. In OOP, if you wait until runtime to decide what should have been encoded in the class design, you pay through branching logic, duplicated code, and hard to understand state.
The broader lesson is this: move invariants upward, move specifics downward, and move filtering as close to the source as possible.
That simple rule improves both database performance and software architecture.
Indexes and Classes: Two Ways of Precomputing Meaning
An index is a precomputed path through data. It is not the data itself, but a structure that lets you arrive at the data without scanning everything. A class works similarly. It is not a living object, but a precomputed pattern for producing objects that behave consistently.
This analogy goes deeper than convenience. Both indexes and classes are commitments about how future work will be organized.
A well chosen index says, “These fields will matter often enough that we should prepare for them.” A well designed class says, “These behaviors recur often enough that they deserve a shared shape.” In both cases, you are trading a little upfront structure for a lot of downstream efficiency.
But there is also a warning hidden in the analogy: precomputation only helps if it matches actual usage.
An index on the wrong column is overhead. A class with the wrong abstraction is overhead too. A method that should be inherited but gets duplicated becomes maintenance debt. A property that should be shared but is redefined in every instance becomes conceptual drift. Likewise, a query that could have used an index but instead wraps the indexed column in a function has defeated its own optimization.
This suggests a practical design test:
If you cannot explain how a structure will reduce future search, comparison, or transformation cost, it may be ornamental rather than useful.
That is true for SQL indexes, and it is true for object oriented abstractions.
Inheritance especially fits this pattern. A child class takes on the attributes and methods of a parent class, then overrides or extends what is different. At its best, inheritance is not about hierarchy for its own sake. It is a way to encode shared structure so the system does not repeatedly solve the same problem.
In database terms, inheritance is like a reusable execution path. In Python terms, it is like telling the interpreter, “Start from the common shape, then specialize only where necessary.” When done well, it reduces duplication. When done badly, it creates fragile coupling. The lesson mirrors indexing: shared structure only helps when it reflects genuine reuse.
The Paradox of Abstraction: Hide Complexity, But Do Not Hide Leverage
Abstraction is usually praised for hiding complexity. That is true, but incomplete. The best abstractions do something more specific: they hide complexity without hiding leverage.
A SQL query becomes worse when it hides the indexed column inside an arithmetic expression, because the optimizer can no longer leverage the index. A Python class becomes worse when its public interface hides too much of the object’s actual role, because other developers can no longer leverage the abstraction to reason clearly about state and behavior.
Consider the __str__ method. It seems small, even cosmetic. But it is an interface decision about how an object reveals itself to the world. A good __str__ implementation does not expose every internal detail. It exposes the right details. It helps debugging, logging, and comprehension without turning the object into a dumping ground.
That same balance appears in query design. You want the database to do the hard work, but you do not want to obscure the query’s intent so much that future readers cannot understand why it is efficient. Elegance without readability is a trap. Readability without structural advantage is also a trap.
The sweet spot is where the shape of the abstraction aligns with the shape of the operation.
Here is a practical way to think about it:
- If you are optimizing SQL, ask whether your predicate lets the engine reason from the stored form of the data.
- If you are designing classes, ask whether the state and behavior live at the correct level of ownership.
- If you are choosing inheritance, ask whether the shared behavior is truly shared, or merely similar.
- If you are defining string output, ask whether the representation reveals the essence of the object, not just its internals.
The aim is not minimalism. The aim is legibility for the system and legibility for humans at the same time.
A Unified Framework: Move Work to Structure
The most powerful synthesis of these ideas is a simple framework: move work to structure.
This means that instead of performing the same reasoning repeatedly at runtime, you encode that reasoning into the arrangement of your data, classes, and methods. SQL indexes move search work into prebuilt structures. Class attributes move shared facts out of instances. Inheritance moves common behavior into a parent class. __init__ moves object setup into a predictable lifecycle. WHERE clauses move rejection earlier in the pipeline.
The result is not just speed. It is stability.
When work is encoded structurally, systems become easier to predict. Queries are easier to tune because their cost follows visible patterns. Classes are easier to maintain because their responsibilities are explicit. Bugs become easier to localize because fewer decisions are deferred to runtime chaos.
A good engineer does not merely ask, “How can I make this faster?” The deeper question is, “How can I make the system less surprised?”
That reframing matters. Surprise is expensive. A database is surprised when you ask it to ignore its indexes. A codebase is surprised when a class mixes shared and instance specific concerns. A maintainer is surprised when behavior is hidden in a function that looks harmless but changes the cost model of everything around it.
If you want a concise law to remember, use this:
The cheapest computation is the one you never ask the system to perform.
Indexes prevent unnecessary scanning. Early filtering prevents unnecessary downstream work. Good class design prevents unnecessary duplication. Inheritance prevents unnecessary redefinition. Meaningful __str__ methods prevent unnecessary confusion.
In each case, the system becomes faster and clearer not by doing more, but by needing less.
Key Takeaways
-
Design for the shape of lookup, not just the shape of data. If the database or reader can find what it needs directly, you save cost everywhere downstream.
-
Filter and specialize as early as possible. In SQL, that means reducing rows before sorting or grouping. In OOP, that means putting shared logic in the class and variable state in the instance.
-
Use structure to precompute meaning. Indexes, class attributes, inheritance, and
__init__all reduce repeated reasoning when they match the real use case. -
Do not hide leverage inside transformations. Wrapping indexed columns in functions or burying important behavior in unclear object design makes the system work harder than necessary.
-
Ask where truth belongs. Shared facts belong at the class level, changing facts belong to instances, and frequently queried data deserves an index or other structural shortcut.
Conclusion: Great Systems Make the Right Thing the Easy Thing
We usually talk about SQL tuning and object oriented design as separate disciplines. One is about speed, the other about architecture. But both are really about the same question: how do you arrange a system so that correct behavior is cheap?
That is the mark of mature engineering. Not cleverness. Not brute force. Not even elegance in isolation. It is the ability to create shapes that absorb complexity before it becomes expensive.
The next time a query feels slow or a class feels awkward, do not start by asking how to make the machine work harder. Ask a deeper question: what hidden structure am I failing to give it? The answer will often lead you to the same insight in both worlds, which is that performance and maintainability begin long before execution. They begin in the model.
And once you see that, optimization stops being a late stage trick. It becomes a way of thinking about reality itself: not as a pile of work, but as a set of structures that either help or hinder the path to truth.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣