矛盾 — a documentation portal for the contradictions inherent in software. Every paradox is a feature, every disagreement a design decision.
// rev. 0.4.7// last touched 2026-05-04// LICENSE: MIT
abstraction vs. clarity
@author mujun · @severity high · @status unresolved
Abstraction promises reuse and elegance. Clarity promises that the next engineer — often you, six months later — can read the code without unrolling three layers of indirection in their head. The contradiction is that good abstractions hide complexity, but the act of hiding is also the act of obscuring.
1+ A well-named function is a frozen idea you never re-think.2- A well-named function is a frozen idea you can no longer question.3+ Abstractions free the mind to operate at a higher level.4- Abstractions hide the bug in the layer below.5+ Names are documentation.6- Names are lies that age faster than code.
The honest position: every abstraction is a debt to a future reader, paid in advance with the hope that the runtime savings will outweigh the inheritance tax. The dishonest position: pretending the tax doesn't exist.
DRY vs. readability
@author mujun · @severity medium · @status live
Don't Repeat Yourself was always a heuristic, never a law. Sometimes a duplicated three-line block is more honest than a parameterized helper that takes seven flags. Two pieces of code can look identical and still mean different things.
1+ Duplication is cheap; the wrong abstraction is expensive.2- Duplication is technical debt accruing interest in the dark.3+ Inline the helper if you have to read its body to use it.4- Inline the helper and now five callers drift independently.5+ Coincidental similarity is not shared meaning.6- Refusing to deduplicate is laziness with a thesaurus.
Read the function. If you reach for the definition before you reach for the next line, the abstraction has failed its only job.
Velocity is a feature until it's a bug. The team that ships every Tuesday has more bugs than the team that ships every quarter, but they also have more users. The contradiction lives in the gap between learning rate and trust rate.
1+ Speed surfaces the real requirements.2- Speed surfaces the real outages.3+ A bug shipped is a hypothesis tested.4- A bug shipped is trust withdrawn.5+ Reverts are cheap; meetings are expensive.6- Reverts are cheap until they cascade.
The honest organization measures both rollback rate and feature velocity. The dishonest one measures only the metric it currently wins on.
explicit vs. implicit
@author mujun · @severity medium · @status live
"Explicit is better than implicit" is a koan that sounds like an order. But every explicit construct is implicit relative to a more verbose alternative. The line moves with the audience.
1+ Explicit code resists surprise.2- Explicit code drowns intent in ceremony.3+ Magic costs you on the day it stops working.4- Magic pays for itself every other day.5+ Defaults are decisions someone else made for you.6- Defaults are decisions you'd rather not make again.
The right answer is contextual: a library should be explicit, an application should be ergonomic, a script should be short. Confuse the contexts and you'll write a framework where you wanted a function.
"Prefer composition over inheritance" became gospel in the 2010s. The original sin is not inheritance — it's deep inheritance. A two-level hierarchy is a free lunch; a six-level hierarchy is a coffin.
1+ Composition is wiring; you can rewire.2- Composition is wiring; the diagram is the program.3+ Inheritance encodes invariants the type system enforces.4- Inheritance encodes invariants no one remembers writing.5+ "is-a" is a strong, useful claim.6- "is-a" is the start of a long apology.
strict vs. permissive
@author mujun · @severity medium · @status live
Postel's law — "be conservative in what you send, liberal in what you accept" — built the internet and then almost broke it. Permissive parsers accept malformed input today and ratify the malformation tomorrow.
1+ Strict input rejects bugs at the door.2- Strict input rejects users at the door.3+ Liberal acceptance is empathy at the protocol level.4- Liberal acceptance is a backward-compat treadmill.5+ Validation is documentation that runs.6- Validation is the wall between you and shipping.
manifesto.md
@author mujun · @status living document
We do not believe in best practices. We believe in tradeoffs that have been argued out loud. Every rule on this site is a rule someone else broke productively last Tuesday.
1+ Document the disagreement, not the conclusion.2+ Prefer raw honesty to polished consensus.3+ The contradiction is the spec.4- "It depends" is not an answer; it's a research project.
contributing.md
@author mujun · @status open
Submit a paradox by opening a pull request against the paradoxes/ directory. Each entry must include both sides — the thesis and the antithesis — with at least three diff lines per side. Resolutions are not accepted.
1+ Both sides must be defensible by a real engineer.2+ No straw arguments. No rhetorical flourish.3- Do not propose a synthesis. The synthesis is the reader.
2024-notes.md
@archived 2025-01-12
Notes from the year microservices stopped being trendy and started being legacy. The contradiction was never about size; it was about ownership boundaries.
1+ Service boundaries follow team boundaries.2- Team boundaries follow service boundaries.3+ Conway's law is a tautology with extra steps.
legacy.md
@archived 2024-08-30
Paradoxes that resolved themselves when the underlying technology changed. Kept here because the shape of the argument is reusable.
1+ Tabs vs. spaces was a religious war.2- Tabs vs. spaces was a tooling failure.3+ The formatter ended the debate, not the argument.