Smell #7: Hidden Dependencies

Severity: High

Hidden Dependencies: Implicit coupling between modules or files that isn't explicitly declared through imports, but is assumed by the AI-generated logic.

Symptoms

How to recognize this smell:

  • [ ] Changing a UI component suddenly breaks a distant API route or database utility.
  • [ ] AI-generated code relies on a specific global state or CSS class without importing or defining it.
  • [ ] You have "Magic Strings" or "Magic Numbers" that must match across multiple files for the system to work.
  • [ ] The codebase feels like a "house of cards"β€”pulling one thread causes an unpredictable collapse.

Self-Assessment

If you checked 2+ items, your codebase has Hidden Dependencies.

Example

The Implicit Redux assumption

AI generates a component:

// Component.jsx
export const TaskItem = ({ id }) => {
  // AI assumes 'tasks' slice exists in global Redux store 
  // and has a specific 'status' field, without checking or defining it.
  const status = useSelector(state => state.tasks.items[id].status);
  return <div>{status}</div>;
}

Why it's bad: If you rename the tasks slice or change the data structure, this component breaks silently. The dependency is "hidden" in the selector logic rather than being an explicit interface.

Debt Impact

This smell is a primary contributor to:

| Debt Category | Impact | |---------------|--------| | πŸ—οΈ ARCH | Tight coupling makes the system impossible to refactor or unit test. | | 🧠 KNOW | Developers don't understand the full "blast radius" of their changes. |

How to Fix

  1. Map the Threads: Use a "call graph" or "dependency visualizer" to find implicit links.
  2. Explicit Interfaces: Define clear Types or Interfaces for data sharing.
  3. Dependency Injection: Pass dependencies as props or arguments rather than relying on global state.

How to Prevent

  • Request Isolation: In your prompts, explicitly ask for "zero external dependencies" for a component.
  • Review for Implicit State: Actively look for window., global., or deep useSelector paths during review.
  • Use TypeScript: Strong typing is the best defense against hidden threads.

Related Smells

Book Reference

  • Chapter 3: Context is King β€” how "flooding" leads to coupling.
  • Chapter 5: Agents Unleashed β€” how agents weave "invisible threads" across files.

Make your dependencies explicit