mujun.dev

矛盾 / contradiction in code

This documentation covers the fundamental contradictions in software engineering -- the paradoxes that every developer encounters but rarely names. Each pattern is documented with the rigor of an API reference, because contradictions deserve formal specification.


Circular Dependencies

Contradiction: Module A requires Module B. Module B requires Module A. Both modules are correct. The system works.

Circular dependencies are treated as anti-patterns, yet they appear in every sufficiently complex system. The contradiction: we design systems to avoid cycles while building on platforms that rely on them.

paradox/circular.js
import { validate } from './schema';
import { parse } from './parser';

// schema.js imports parser
// parser.js imports schema
// both are correct. both must exist.

export function resolve(input) {
  const parsed = parse(input);
  return validate(parsed);
  // the circle completes
}

Resolution: Accept the cycle. Introduce a shared interface that both modules implement, letting the dependency point inward rather than across. The contradiction remains, but its shape becomes manageable.


The Observer's Paradox in Debugging

Contradiction: Adding a console.log statement changes the timing. The bug disappears. Removing the log brings the bug back. The act of observing alters the system.

Heisenbugs are the software embodiment of the observer effect. The debugger changes thread scheduling. The log statement introduces a delay. The breakpoint alters memory layout. You cannot observe the system without becoming part of it.

paradox/observer.js
async function fetchData() {
  const result = await api.get('/data');
  // Bug: result is undefined

  console.log(result);
  // With this line: result is defined
  // Without this line: result is undefined
  // The observation creates the value

  return result;
}

Resolution: There is no resolution. You can mitigate (deterministic replay, time-travel debugging) but you cannot eliminate the paradox. The observer is always part of the system.


Premature Optimization vs. Technical Debt

Contradiction: "Don't optimize early" and "Don't accumulate debt" are both correct. Following either fully prevents you from following the other.

Knuth says premature optimization is the root of all evil. Ward Cunningham says technical debt compounds. Both are right. The contradiction forces a perpetual negotiation between speed-now and speed-later.

paradox/optimize.ts
// Version 1: "Ship it" (accrues debt)
function search(items: Item[], q: string): Item[] {
  return items.filter(i =>
    JSON.stringify(i).includes(q)
  );
}

// Version 2: "Do it right" (premature?)
function search(items: Item[], q: string): Item[] {
  const index = buildTrie(items);
  return index.query(q);
}

// Both are wrong. Both are right.

Resolution: There is no universal answer. The contradiction is the methodology -- oscillate between the two poles, choosing based on context, never committing fully to either doctrine.


The Halting Problem

Contradiction: We build systems to detect failures. We cannot build a system that detects all failures. We build them anyway.

Turing proved no general algorithm can determine if an arbitrary program halts. Yet every production system has health checks, timeouts, and watchdogs -- approximations of the impossible.

paradox/halting.js
function willItHalt(program) {
  // This function cannot exist.
  // Yet here it is.

  try {
    const timeout = setTimeout(() => {
      throw new Error('Assumed halt');
    }, 5000);
    program();
    clearTimeout(timeout);
    return true;
  } catch {
    return 'maybe';
  }
}

Resolution: Replace certainty with probability. We cannot know if a program halts, but we can know if it hasn't halted yet. The watchdog timer is an admission of impossibility dressed as engineering pragmatism.


Process Notes

This documentation is itself a contradiction: a static document describing dynamic paradoxes. A formal specification of things that resist specification. The format (technical docs) contradicts the content (the limits of technical thinking).

Every software project contains contradictions. The goal is not to eliminate them but to document them with sufficient clarity that they become navigable. Contradiction is not a bug -- it is a feature of sufficiently complex systems.

矛盾 -- the spear that pierces any shield, the shield that blocks any spear. Both exist. The system works.