Why Good Software Is Mostly About Choosing What Not to Remember
Hatched by Kai Nguyen
Jun 18, 2026
10 min read
2 views
88%
The hidden question behind every data structure
What if the hardest part of programming is not making software do more, but deciding what it should refuse to do?
That sounds odd until you notice how the core data structures all impose a discipline on information. An array says: stay in order, stay adjacent, stay fixed. A linked list says: remain flexible, but accept the cost of following pointers. A stack says: only the top matters. A queue says: patience is part of the design. A tree says: reality has hierarchy. A graph says: reality has relationships. A hash table says: forget the path, remember the key.
In other words, data structures are not just containers. They are policies of memory. They decide whether software remembers position, sequence, ancestry, connection, or identity. Once you see that, a second pattern appears: good code documentation works the same way. A docstring does not merely repeat what the code does. It tells future readers what matters, what is obvious, and what needs more explanation. It places a small, readable boundary around complexity.
The deeper connection is this: both documentation and data structures are methods for taming complexity by making trade-offs explicit. One governs how humans revisit knowledge. The other governs how machines access it. And in both cases, clarity comes from restraint.
Every structure is a promise, and every promise has a cost
The seductive myth in software is that a better abstraction removes trade-offs. In practice, the best abstractions make trade-offs visible and intentional.
Consider the array. It is the classic example of speed through arrangement. Elements live in contiguous memory, so random access is fast and direct. If you know exactly where something is, you can get there immediately. That makes arrays ideal for fixed collections, indexing, sorting, and any workload where location matters more than churn.
But arrays are also stubborn. Insert in the middle, and you may have to shift many elements. Grow them too often, and the cost becomes noisy and expensive. An array is a bargain: you get speed because you agree to stability.
A linked list makes a different bargain. Instead of physical contiguity, it offers dynamic movement. Insertions and deletions become cheap because nodes can be rewired rather than relocated. That flexibility feels elegant until you need random access. Then the list reveals its tax: you must traverse from node to node, following the chain one step at a time.
This pattern repeats across the rest of the family:
- A stack protects the past by hiding it beneath the present. It is ideal for function calls, undo operations, and backtracking, but it refuses arbitrary access.
- A queue preserves fairness by serving elements in arrival order, which is perfect for tasks, scheduling, and breadth first exploration, but it cannot easily prioritize based on meaning.
- A tree organizes information into levels of parent and child, which makes hierarchy legible, but it can become awkward when relationships are not hierarchical at all.
- A graph models interconnection beautifully, but its richness creates complexity in traversal and search.
- A hash table makes retrieval feel almost magical by jumping straight to a key, but that speed comes with the risk of collisions and the loss of order.
A data structure is not mainly a way to store data. It is a way to declare what kind of access your problem deserves.
This is why choosing the wrong structure often feels like software fighting itself. The code is technically correct, but the underlying assumptions are mismatched. If the data changes constantly, a fixed array resists you. If lookup speed matters more than order, a queue or list may waste time. If relationships are complex, a tree will flatten nuance. If order is everything, a hash table will feel like amnesia.
The right structure is not the one with the most impressive performance number. It is the one whose limitations match the shape of the problem.
Documentation is the human version of data structure design
At first glance, docstring conventions and data structure theory seem to belong to different worlds. One is about writing comments. The other is about memory organization and algorithmic behavior. But both are really about how to make complexity navigable.
A docstring has structure for the same reason a data structure does. A one line docstring is for something genuinely obvious. If the code already reads like its purpose, do not clutter the page. If more explanation is needed, use a summary line, followed by a blank line, followed by a fuller description. That pattern mirrors the choice between a simple and complex structure: minimalism when the problem is small, elaboration when the problem demands it.
There is also a deeper parallel in the idea of attribute docstrings and additional docstrings. Those concepts acknowledge that meaning does not live only in the primary object. Sometimes an attribute or secondary element deserves its own explanation. Likewise, not every software question belongs in the main data path. Sometimes the metadata, the invariants, or the operational context are the real story.
This matters because code is read far more often than it is written. A good docstring is not a note to the compiler. It is a contract with the future. It tells the next person what the function assumes, what it guarantees, and what would be risky to change. That is exactly what a well chosen data structure does too. It tells the next algorithm what kind of access will be cheap, what kind will be expensive, and what kind will be unnatural.
Here is the surprising synthesis: documentation and data structures are both interfaces to intention.
When you write a docstring, you are compressing thought into an accessible format. When you pick a data structure, you are compressing behavior into an efficient format. In both cases, the goal is not completeness. The goal is useful constraint.
A bad docstring says too little or too much. A bad data structure does the same. It either hides important assumptions or burdens every operation with unnecessary complexity. Good software, then, is not the absence of structure. It is the presence of the right amount of structure, in the right place.
The real skill is not memorizing types, but reading the shape of a problem
Most developers learn arrays, linked lists, stacks, queues, trees, graphs, and hash tables as a list of tools. That is necessary, but not sufficient. The real skill begins when you can look at a problem and recognize its native geometry.
Ask four questions:
- Is the data mostly fixed or changing?
- Do I need random access or sequential access?
- Is the important relationship order, hierarchy, or connection?
- Will I care more about lookup speed, mutation speed, or memory use?
Those questions are more useful than memorizing big O notation alone, because complexity is not abstract. It expresses lived constraints. An array is efficient because the data is contiguous. A linked list is flexible because nodes can move independently. A stack is efficient because it only needs the top. A queue is efficient because it only needs front and back. A tree is efficient because it prunes search space through hierarchy. A graph is necessary when the world is not a tree at all. A hash table is fast because it converts meaning into location.
A few concrete examples make the logic vivid:
- Undo in a text editor: a stack fits because the most recent action is the first one you want to reverse.
- Browser history: a stack or a doubly linked list works because users need to move backward and forward through recent states.
- Printer jobs or task scheduling: a queue fits because fairness matters more than instant access to arbitrary entries.
- File systems and organizational charts: trees fit because they represent nested structure naturally.
- Social networks, routing systems, recommendation engines: graphs fit because the world is webbed with many to many relationships.
- Caching and database indexing: hash tables fit because speed of lookup is the priority.
The mistake many systems make is to choose based on familiarity instead of shape. Arrays feel simple, so they get used everywhere. Hash tables feel powerful, so they get used when order actually matters. Trees feel elegant, so they get used even when the data is not hierarchical. The expert move is to reverse the question: what structure would make this problem feel almost inevitable?
That is also the right question for documentation. What explanation would make this function feel inevitable to the next reader? What assumption would otherwise become a hidden bug?
In both domains, the goal is to reduce surprise.
The best structure does not merely solve the problem. It makes the problem easier to think about.
A practical mental model: choose the memory that matches the failure mode
Here is a useful framework that goes beyond a simple list of pros and cons.
Every software system fails in one of a few recurring ways:
- It becomes too slow to access.
- It becomes too expensive to modify.
- It becomes too hard to understand.
- It becomes too rigid to evolve.
- It becomes too loose to trust.
Different structures defend against different failures.
Arrays defend against slow access. Their failure mode is mutation cost.
Linked lists defend against mutation cost. Their failure mode is traversal cost.
Stacks defend against decision overload by limiting access. Their failure mode is narrowness.
Queues defend against unfairness and disorder. Their failure mode is inflexibility about priority.
Trees defend against chaos by imposing hierarchy. Their failure mode is imbalance or over modeling.
Graphs defend against oversimplification when relationships are many to many. Their failure mode is complexity explosion.
Hash tables defend against lookup slowness. Their failure mode is collisions, loss of order, and memory overhead.
This lens is powerful because it turns architecture into risk management. You are not just selecting a structure that is fast in the happy path. You are choosing which kind of pain you are willing to tolerate when the system changes.
The same lens applies to docstrings. A one line docstring is efficient, but it fails when there are important invariants, edge cases, or side effects. A longer docstring is informative, but it fails when it becomes noise. Good documentation chooses the failure mode you can live with. It prefers to be slightly incomplete rather than misleading. It prefers clarity over cleverness. It uses triple double quotes not because syntax is sacred, but because consistency lowers cognitive friction.
That consistency is itself a design choice. Humans, like machines, process predictable patterns more efficiently. Just as contiguous array memory enables fast access, consistent documentation structure enables fast understanding.
Key Takeaways
-
Treat data structures as policies, not containers. Each one defines what kind of access is cheap and what kind is expensive.
-
Match the structure to the shape of the problem. Fixed and random access suggest arrays or hash tables. Frequent updates suggest linked lists. Hierarchies suggest trees. Relationships suggest graphs. Order sensitive workflows suggest stacks or queues.
-
Write documentation with the same discipline. Use the smallest explanation that still makes the code obvious to a future reader. Add more only when the hidden assumptions matter.
-
Choose the failure mode you can tolerate. Every structure trades one kind of pain for another. The best choice is the one whose weaknesses are least harmful in your context.
-
Optimize for the next person as much as for the machine. Good design reduces both computational cost and mental cost.
The deeper lesson: software is an exercise in disciplined forgetting
We often talk about software as if its job is to remember everything. In reality, software becomes elegant when it remembers only what matters.
An array remembers position. A linked list remembers sequence. A stack remembers recency. A queue remembers arrival order. A tree remembers hierarchy. A graph remembers connection. A hash table remembers identity. A docstring remembers intention.
That is the unifying insight. The central challenge in programming is not storing more. It is deciding what kind of memory serves the task and what kind of memory would only create burden.
This is why the best systems feel almost quiet. They do not force you to fight the wrong abstraction. They do not make you search in a place where search is expensive, or update where updates are painful, or explain where explanation should have been obvious. They align structure with expectation.
So the next time you choose a data structure, or write a docstring, ask a deeper question than which option is faster. Ask: what am I asking the system to remember, and what am I asking it to forget?
That question will lead you closer to software that is not just efficient, but intelligible. And intelligibility, in the long run, is the rarest kind of performance gain.
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 🐣