Your Dependency Graph Already Knows Your Architecture

repoclojurearchitecturevisualizationdependency-graphtoolingstatic-analysis

Topological namespace layering could surface package boundary violations in the joelclaw monorepo before they calcify — directly relevant to ADR-0144 hexagonal architecture enforcement.

Uncle Bob Martin — the Clean Code and Clean Architecture author — built a Clojure tool that does something quietly smart: instead of asking you to label what’s “high-level” versus “implementation detail,” it extracts your namespace dependency graph and runs topological sorting to figure that out. Namespaces that nothing else depends on float to the top. Leaf namespaces with no outbound project dependencies sink to the bottom. The layout algorithm decides the architectural hierarchy, not a developer with a whiteboard.

The output is an interactive SVG. You can click into any non-leaf namespace to drill down, replacing the scene with that namespace as the new root. Click a leaf namespace to open its source. Navigate back up with a toolbar button. The tool also marks polymorphic namespaces — those containing defprotocol, defmulti, or definterface — as abstract, rendering them in green instead of blue. Incoming and outgoing dependency directions get small triangle indicators on namespace edges; hovering over them opens a popup showing the actual dependency paths.

The cycle handling is the genuinely clever bit. Cycles break topological sorting, so the tool identifies offending edges, removes them before the ranking pass to get a clean acyclic graph, runs the sort, then renders the removed cycles back as red indicators in the final diagram. Red names, red triangles, red paths in the hover popup. You get a properly sorted architectural view and full visibility into your cyclic debt in the same diagram. It doesn’t hide what hurts.

It’s Clojure-specific — reads ns forms and :require clauses — so it won’t run on a TypeScript monorepo directly. But the underlying idea is generalizable: let the dependency graph determine architectural layers rather than hand-labeling them. Something like this applied to the package graph in the joelclaw monorepo — which enforces strict package boundaries under ADR-0144 — could surface cross-package violations before they become load-bearing.

Key Ideas

  • Topological sorting as architecture documentation — dependency depth determines layer position automatically; no manual labeling required
  • Cycle-aware layout without cycle hiding — cycles are removed from the ranking algorithm but rendered back as red visual indicators, so both the clean view and the debt are visible simultaneously
  • Abstract namespace detectiondefprotocol, defmulti, definterface get marked as abstract (green), distinguishing interface namespaces from concrete implementations
  • Drill-down navigation — interactive SVG lets you explore the architecture hierarchically, clicking into sub-namespaces and back out
  • Headless EDN export--no-gui --out /tmp/architecture.edn for pipeline use, CI integration, or diff-over-time tracking
  • Uncle Bob’s own tooling — the examples include empire-2025.architecture.edn, the “Empire” system he uses as a reference project across his books
  • The concept generalizes — the topological-sort approach to architectural layering applies to any language with a parseable dependency graph; ts-morph or similar could do this for TypeScript packages