The Future Can Only Change What You Keep Separate
Hatched by Tom Haus
Aug 06, 2026
10 min read
2 views
94%
What if the difference between beginner work and expert work is not intelligence, speed, or even experience, but the number of future problems one decision quietly creates?
A note that mixes three unrelated ideas becomes difficult to reuse. A function that validates input, transforms it, and writes to a database becomes difficult to change. These look like different failures: one belongs to personal knowledge management, the other to software engineering. Yet both reveal the same deeper problem.
When too many responsibilities are fused together, change becomes expensive because every future decision must first untangle the past.
The remedy is not fragmentation for its own sake. It is the disciplined creation of units that are small enough to understand, independent enough to reuse, and coherent enough to remain meaningful. This is the deeper connection between atomic notes and maintainable code: both are forms of architecture for the future mind.
The hidden cost of putting everything in one place
Consider a note titled “Hard determinism and moral responsibility.” It may contain assumptions about causality, arguments about agency, objections from compatibilism, and a conclusion about blame. At first, this feels efficient. Everything is available in one location. The note may even read smoothly.
But its convenience is temporary. Later, you may want to reuse the argument about responsibility without accepting hard determinism as an assumption. If the two are fused, reuse requires copying, editing, and mentally separating claims that were never meant to be inseparable. The note has become a container, but not a useful component.
The same thing happens in code. Imagine a function called createUser that performs all of the following:
- Checks whether an email address is valid.
- Normalizes the address and name.
- Checks for duplicates.
- Writes the user to a database.
- Sends a welcome email.
- Formats an error message for the interface.
The function may work perfectly today. Its problem is not present functionality. Its problem is that it has made several different kinds of change dependent on one another. A change to validation can affect persistence. A new email provider can affect user creation. A different interface can force database logic to change because the error message was constructed in the same place.
This is coupling disguised as convenience.
The immediate version of a system rewards consolidation. One note is easier to write than five. One function is faster to assemble than a set of carefully defined functions. But the future version of the system pays the bill. When requirements shift, when a teammate arrives, or when an incident begins at two in the morning, the original convenience turns into investigation.
The real measure of simplicity is not how little you build today. It is how little you must understand before making a safe change tomorrow.
Atomicity is not smallness. It is a boundary around a decision
The word “atomic” can mislead. It does not mean that every note should contain one sentence or that every function should be tiny. A fragment can be so small that it loses its purpose. A function that wraps a single line without clarifying anything is not well designed. It is merely ceremonially divided.
Atomicity means that a unit has one primary reason to change.
A note about the assumptions of hard determinism should be separate from a note about moral responsibility under those assumptions because the two may change independently. A function that validates an email should be separate from a function that persists a user because validation rules and storage requirements are different sources of change.
This gives us a more useful test than counting lines or paragraphs:
If two parts could change for different reasons, they probably deserve different boundaries.
That test also explains why atomicity produces reuse. A reusable unit is not simply a small unit. It is a unit whose meaning can travel without dragging irrelevant commitments along with it.
A general argument can be reused in several philosophical contexts because it is not fused to one disputed premise. A normalization routine can be reused across registration, importing, and account recovery because it is not fused to a particular database operation. In both cases, separation preserves optionality.
This is why a good note title behaves like an application programming interface. A title such as “Moral responsibility requires control” makes a claim that another note can understand and connect to. A title such as “Thoughts about responsibility” offers little surface area for connection. The first tells the rest of the system what the component does. The second makes every reader open the component and inspect its contents.
Good interfaces do the same thing in software. They expose a clear promise while hiding unnecessary implementation details. A function called normalizeEmail communicates a stable operation. A function called processUserData forces the reader to discover what “process” means, and perhaps what unrelated operations are concealed within it.
The real enemy is cognitive overflow
Why does this matter so much during maintenance? Because humans are not good at holding many active relationships in working memory, especially under pressure.
During a calm afternoon, a developer may understand a large function by tracing its branches. During an incident, that same function becomes a maze. The reader must remember validation rules, database behavior, retry logic, error formatting, and side effects at once. Every additional responsibility increases the chance that an apparently safe change will produce an unexpected failure.
A practical rule follows: if understanding a unit requires holding more than a few important things in your head at once, the unit is asking to be refactored.
This is not a rigid mathematical law. Some domains are intrinsically complex. But complexity should be located in the problem, not amplified by the structure of our notes and code. A well designed system may contain difficult ideas while ensuring that each local decision has a narrow field of view.
Imagine an emergency room with a single chart containing every patient, medication, diagnosis, and procedure written in chronological order. The information might all be present, but the structure would be unusable. Medical practice depends on boundaries: one patient, one case, one medication order, one decision at a time. Those boundaries do not eliminate complexity. They make complexity navigable.
Atomic notes and functions serve the same purpose. They reduce the distance between a question and the material needed to answer it.
This also explains the importance of writing for the future reader, including your future self. At two in the morning, nobody benefits from cleverness that requires reconstruction. The reader needs to know what a component does, what it assumes, what can fail, and what it does not do.
Clarity is not decoration added after the work. Clarity is part of the work's reliability.
Design for change, not merely for completion
A system is often judged by whether it produces the desired result. That is necessary, but incomplete. Mature design asks a second question: what happens when the surrounding conditions change?
Requirements do not shift randomly. They tend to move along recognizable dimensions:
- Inputs change. New formats, edge cases, users, or sources appear.
- Rules change. A policy, assumption, or business requirement is revised.
- Outputs change. The same underlying result must be presented to a new audience or system.
- Failures change. A previously rare error becomes common, or a new recovery path is required.
- Context changes. Another person must understand, test, reuse, or replace the component.
A fused unit is vulnerable along all five dimensions. A unit with clear boundaries localizes the damage.
Suppose a product changes its rule for valid email addresses. If validation is isolated, the change should mostly remain in the validation component and its tests. If validation is fused with user creation, notification, and interface messaging, the same rule change becomes an archaeological expedition.
The same principle applies to intellectual work. Suppose you revise your view of hard determinism but still find one argument about responsibility useful. If your assumptions, argument, and conclusion were recorded as separate units, revision becomes selective. You can replace one component without destroying the network around it.
This is the overlooked relationship between atomicity and learning. Learning is not only accumulation. It is revision. A knowledge system that stores ideas in inseparable bundles makes disagreement expensive because changing one belief threatens many others. A more modular system allows a person to say, “I no longer accept this premise, but I still accept that method,” or, “This conclusion was wrong, but the evidence remains useful.”
Modularity therefore protects intellectual honesty. It lets us update beliefs without treating every revision as total collapse.
The failure path is where architecture becomes visible
One of the strongest tests of a design is not what happens when everything goes right. It is what happens when a reasonable thing goes wrong.
A success path can conceal coupling. A request arrives, the function runs, the record is saved, and everyone leaves satisfied. Failure exposes the actual architecture. What happens if the input is malformed? If the database succeeds but the email fails? If the operation is retried? If the user sees an error even though the record was created? If a teammate must diagnose the issue without knowing the history of the code?
These are not edge concerns. They reveal whether responsibilities have been separated according to their different failure modes.
The same is true of notes. A note may appear coherent while you agree with everything inside it. The test comes when you question one claim. Can you reject an assumption without rewriting the argument? Can you connect a useful concept to a new topic without importing the old conclusion? Can you tell which statement is evidence, which is interpretation, and which is a proposed implication?
A useful practice is to list failure modes before polishing the happy path. For code, ask:
- What can fail before the operation begins?
- What can fail after a partial success?
- Which errors should be retried, and which should not?
- What would confuse someone diagnosing this later?
For notes, ask:
- Which claim here depends on another claim?
- Which parts could be useful even if the conclusion changes?
- What would I want to link to from somewhere else?
- Can the title state a proposition rather than merely name a topic?
In both domains, failure analysis improves structure because it forces hidden dependencies into view.
A practical architecture for durable thinking
You can apply this synthesis with a simple three layer model.
1. Separate commitments from operations
In knowledge work, distinguish assumptions, evidence, arguments, conclusions, examples, and open questions. In code, distinguish validation, transformation, decision making, persistence, side effects, and presentation.
The goal is not to create a separate container for every sentence or line. The goal is to prevent one kind of commitment from pretending to be another kind of operation.
2. Give each unit a sharp promise
A useful title or function name should let a reader predict what belongs inside and what does not. Prefer statements such as “Clear interfaces reduce the cost of future change” over labels such as “Interfaces.” Prefer calculateShippingCost over handleOrder when the latter hides several responsibilities.
A sharp promise improves discovery, testing, review, and reuse simultaneously. It is a small investment that pays across the entire system.
3. Connect units through explicit relationships
Atomicity without connection creates a pile of fragments. The answer is not to put everything back into large containers. It is to make the relationships visible.
Link a note to the assumption it challenges, the argument it supports, and the example that clarifies it. In code, make data flow and dependencies explicit. A component should not need to know every detail of its surroundings in order to function.
The aim is a network of understandable parts, not a collection of isolated parts.
Key Takeaways
- Split by reason to change, not by arbitrary size. If two responsibilities respond to different future requirements, give them different boundaries.
- Treat names as interfaces. Use titles and function names that make a clear promise about what the unit does.
- Design around failure paths. Ask what happens during partial success, invalid input, retries, misunderstanding, and handoff.
- Protect reusable claims and operations from irrelevant commitments. Keep assumptions separate from arguments, and validation separate from persistence.
- Optimize for the future reader. Make the structure understandable when context, time, and attention are scarce.
The deepest lesson is that maintainability is a form of consideration. It is consideration for the person who will inherit the code, for the reader who will encounter the idea in a new context, and for the future version of yourself who has forgotten why the original decision seemed obvious.
A completed system answers the question, “Does it work?” A durable system also answers, “Can someone safely change it without understanding everything?”
That is why the best notes and the best code share a quiet virtue. They do not merely contain intelligence. They organize intelligence so that it can survive revision, disagreement, failure, and time. The expert move is not to make the present look simple by hiding complexity inside a large container. It is to place each complexity where it can be understood, tested, replaced, and reused.
The future does not inherit your intentions. It inherits your boundaries.
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 🐣