The Hidden Grammar of Systems: Why Objects and Windows Are the Same Mental Move

Kai Nguyen

Hatched by Kai Nguyen

Jun 10, 2026

10 min read

72%

0

The surprising question beneath both code and queries

What if the real skill in software is not writing more logic, but deciding where a fact lives and how long it stays local?

That question quietly connects two ideas that are usually taught separately. In one world, you build objects with classes, instance attributes, class attributes, methods, and inheritance. In the other, you use CTEs, partitions, and window functions to shape SQL into something more understandable and more powerful. At first glance, one is about application design and the other is about data analysis. But both are really about the same thing: creating boundaries that let complexity become legible.

The deep tension is this: real systems are messy, but good abstractions pretend the mess has shape. Objects say, “These properties belong together.” Window functions say, “These rows belong together for this calculation.” Both are acts of deliberate grouping. Both make a flood of details navigable without destroying the underlying reality.

Good abstraction does not remove complexity. It gives complexity a place to stand.


Objects are not things, they are agreements about behavior

A class is often described as a blueprint, but that description undersells it. A blueprint suggests a static plan. A class is more like a contract for meaning. It says which data should travel together, which behaviors belong to that data, and which parts are shared across all instances versus unique to each one.

That distinction matters because it reveals the real value of object-oriented design: not simply organization, but ownership of state. An instance stores real data. Attributes created in __init__ vary from object to object. Class attributes represent values that should remain constant across the family. Methods define what the object can do with its own state. Inheritance then lets one object type extend or specialize another without rewriting the whole story.

This is why custom objects are powerful even when they look mundane. They give your program a vocabulary that matches the domain. A Customer, Invoice, or Sensor object is not just a container. It is a way of declaring that certain facts should move together because they describe one coherent entity. Once that coherence exists, the code becomes easier to change because the system has fewer invisible dependencies.

A useful mental model is to think of an object as a small republic of data and behavior. The instance attributes are local laws. The class attributes are constitutional principles. Methods are the procedures that interpret those laws. Inheritance is federalism, a way to share structure while allowing local variation.

This is not merely a coding style. It is a philosophy of semantic clustering: if two facts always travel together in the real world, the code should try to keep them together too.


SQL window functions solve the same problem, but at the level of rows

SQL looks different because it speaks in sets rather than objects, but the underlying move is strikingly similar. A WITH clause creates a CTE, which is a named intermediate result. A PARTITION BY clause groups rows into meaningful subsets. A window function then performs a calculation across each subset without collapsing the rows the way a standard aggregate would.

That last detail is the key. An aggregate function says, “Combine these rows into one result.” A window function says, “Look across these rows, but preserve each row’s identity.” That is a profoundly object-like idea. You are giving the data a local context, a scope in which a calculation makes sense, while keeping the original entities visible.

For example, imagine a sales table. If you want total revenue by region, an aggregate is enough. But if you want each sale to carry its rank within a region, or compare itself to the average of its peers, a window function becomes essential. The row is still a row, but now it participates in a group with a specific purpose.

That is exactly what object-oriented design does with methods and attributes. Each instance remains distinct, but it is interpreted through the context of its class. The class is not a prison. It is a window of meaning through which the instance becomes intelligible.

CTEs add another layer to this picture. They are not just convenience syntax. They are a way of naming a step in reasoning. Instead of forcing the reader to decode a single monolithic query, a CTE creates an explicit intermediate concept. It says: before we rank, filter, or compare, let us first define the relevant subset. That is the SQL equivalent of separating instance attributes from class attributes, or splitting a large behavior into methods.

The shared insight is simple but powerful: structure precedes computation. You do not begin with the answer. You begin by deciding how the answer should be framed.


The real abstraction is not code reuse, it is context reuse

Most people think classes are mainly about reusing code, and SQL windows are mainly about reusing calculations. But the deeper benefit is not reuse. It is context reuse.

A context is the set of facts that make a statement meaningful. In an object, context includes the object’s state, its shared class properties, and the methods available to it. In a windowed SQL calculation, context includes the partition, the ordering, and the rows that sit inside the frame of reference. Without context, a value is just a value. With context, it becomes a decision, a comparison, a rank, a role.

Consider a simple analogy: a word in a sentence versus the same word in a dictionary. The dictionary gives you the isolated definition. The sentence gives you the living meaning. Objects and window functions both work like sentences. They make sure each element is understood in relation to what surrounds it.

This is why the best abstractions are often local rather than global. They do not try to describe the whole system at once. They carve out a working neighborhood where certain operations are valid. A method on an object assumes its instance data is already present. A window function assumes its partition has already been defined. A CTE assumes one stage of logic has already been made explicit.

The most useful abstraction is often not the one that hides complexity. It is the one that gives complexity a stable coordinate system.

This reframes how we think about maintainability. Maintainability is not just about fewer lines of code or shorter queries. It is about making the system easier to reason about because every fact has a place, every place has a scope, and every scope has a name.


Inheritance and partitions: two ways to say “same, but different”

Inheritance and PARTITION BY may seem unrelated, but both are mechanisms for expressing shared structure with controlled variation.

Inheritance says that a child class should inherit the common traits of a parent while adding or overriding what differs. That is useful when many entities share a base identity but diverge in important details. A Vehicle class might define shared movement logic, while Car and Truck specialize that logic differently.

Partitioning does something analogous in SQL. It groups rows by a shared key, such as region, user, or category, so that a calculation can respect local differences. A rank within one partition has no meaning outside that partition. A sale in one region competes only with its neighbors in that region. That is a form of inheritance in reverse: the group shares a structure, but each partition maintains its own internal reality.

The deeper parallel is not the mechanism itself. It is the recognition that comparison is always local. A child class is compared to its parent and siblings through a chain of relationships. A row is compared to other rows in its partition. In both cases, the meaning of an element depends on the frame you choose.

This is where many systems fail. They use global rules where local rules are needed, or local rules where global consistency matters. They flatten distinctions that should remain separate, or they fragment things that should remain unified. The art is knowing whether a domain needs a shared base or a scoped comparison.

A practical rule emerges:

  1. Use a shared structure when the behavior is fundamentally the same.
  2. Use partitioning when the calculation should respect local neighborhoods.
  3. Use overrides or specialized methods when the variation is not incidental but essential.

In other words, decide first whether the system needs a family resemblance or a peer group.


Why these patterns feel intuitive once you see them

People often struggle with object-oriented design and SQL window functions for the same reason: both require you to think in terms of relationships before results. Beginners want to ask, “What is the answer?” Good designers ask, “What is the shape of the problem?”

That shift is uncomfortable because it delays gratification. Instead of writing the final formula directly, you define a class first or build a CTE first. Instead of reducing data immediately, you let rows coexist in a window long enough to reveal patterns. Instead of treating everything as a flat list of facts, you organize facts into local environments.

This is also why these tools are so effective in debugging. A class lets you inspect the state of a single entity with predictable behavior. A CTE lets you inspect an intermediate result before it gets folded into later logic. A window function lets you understand each row while still seeing the surrounding group. Each one provides a place where uncertainty becomes visible.

Think of it like architecture. A building is not useful because it contains materials. It is useful because it creates rooms, hallways, and thresholds. Those boundaries do not eliminate space. They make space livable. Classes, CTEs, and windows do the same thing for thought. They turn undifferentiated complexity into traversable structure.

The key insight is that abstraction is not escape. It is guided attention. It tells you which details matter together, which should remain separate, and which calculations should be performed in a shared frame.


Key Takeaways

  • Ask where a fact belongs before asking what to do with it. If you cannot say whether a value is instance-level, class-level, or group-level, your design is probably still too vague.
  • Prefer local context over global flattening. Objects and window functions both work because they preserve identity while adding meaning through context.
  • Use intermediate names to make reasoning visible. A CTE or a well-named method is not just convenience, it is a checkpoint for thought.
  • Treat partitioning and inheritance as opposite answers to the same question. One organizes by shared peer group, the other by shared lineage. Choose based on how variation actually behaves.
  • Design for interpretation, not just execution. The best structures help humans understand what the system is doing, not merely make the machine finish faster.

The hidden grammar of systems

The most interesting connection between objects and windows is not technical. It is grammatical. Both are ways of giving a system nouns, verbs, and clauses. An object bundles attributes and behaviors into a coherent unit. A window gives rows a shared clause in which a calculation can be interpreted. A CTE names an intermediate sentence. Inheritance extends a sentence family without rewriting the language.

This suggests a deeper principle: good systems are not just efficient, they are syntactically honest. They express reality in units that mirror how the reality is experienced. A customer is not just a row. A sale is not just a number. A region is not just a filter. Each one lives in a different layer of meaning, and the best tools help us respect that layering.

So the next time you reach for a class or a window function, do not think only about syntax. Ask a more interesting question: what kind of relationship does this problem deserve? Is it a shared identity, a local comparison, a reusable context, or a specialized descendant? The answer will shape not just your code, but your understanding of the domain itself.

In that sense, object-oriented programming and SQL analytics are not two separate topics. They are two dialects of the same discipline: making structure visible so that meaning can emerge. Once you see that, you stop writing code and queries as collections of instructions, and start composing them as models of how the world is organized.

Sources

← Back to Library

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 🐣