Stratify
Explore and improve architecture of software, visualize structure and dependencies of codebases, calculate code metrics
Install / Use
/learn @dundalek/StratifyREADME
Stratify
Stratify is a tool for exploring and improving architecture of software. Discover bits of Stratified Design that are hiding in your code. Gain big picture understanding to make better decisions how to grow your system.
Features and sources:
- Code maps - Visualize structure and dependencies of codebases, supports following sources:
- Source code - C/C++, Clojure, Go, Java, JavaScript/TypeScript, Lua, Python, Ruby, Rust, Zig
- Graphviz - Interactive visualization of outputs produced by other tools
(e.g. Go, JavaSript/TypeScript dependencies or others) - Architecture maps - Explore C4 models
- Infrastructure maps - Infrastructure-as-Code (IaC) using Pulumi or SST
- Metrics reports - Calculate code metrics and generate visual reports
- Architecture checks - Enforce architectural constrains, dependency rules, layer violations
Visualization renderers:
- DGML - For visualization it leverages the code map tool from Visual Studio, which is designed for hierarchical graphs, and allows to interactively collapse or expand the amount of shown information.
- 3D Code City - Outputs data for use with CodeCharta tool to visualize codebase and metrics in 3D view.
- 3D Code Galaxy - Outputs data for use with the Dep-Tree visualizer that uses 3D force layout view.
DGML Renderer
This is an advantage over static graph rendering tools like Graphviz which only work for trivial sized graphs, because for a size of systems encountered in practice it becomes a tangle of lines. That is overwhelming and does not aid much in understanding the structure.
| | |
| - | - |
|
|
|
|
|
|
The code map tool in Visual Studio uses DGML, which is an XML-based format for representing directed graphs. Visualizing a codebase is a two step process:
- First, this tool reads Clojure code and outputs a DGML graph.
- Then the graph is loaded and visualized using the DGML Editor in Visual Studio.
3D Code City Renderer
Additionally, Clojure code can be extracted to CodeCharta format to visualize it as 3D Code City. In this view code metrics can be mapped to visualization to uncover hotspots or areas that need attention. See details.

3D Galaxy Renderer
There is also support for the Dep-Tree visualizer which uses 3D force layout. The way the nodes are spread into clusters can be used to judge modularity of a codebase. See instructions.

Demos and Talks
Watch the demo video which shows several use cases:
- Big picture understanding - Explore a codebase top-down to gain insights about the system structure.
- Local understanding - Navigate and traverse the call graph to learn details about implementation.
- Refactoring simulation - Improve structure of a codebase by previewing results of refactoring.
Watch the London Clojurians talk that goes into depth and also discusses software architecture in general:
Usage
First extract DGML graph from source code.
Use without installing
clojure -Sdeps '{:deps{io.github.dundalek/stratify{:git/tag"v0.4.0":git/sha"48726c2"}}}' \
-M -m stratify.main
Install by adding alias
~/.clojure/deps.edn to :aliases section
{:aliases
{:stratify
{:extra-deps {io.github.dundalek/stratify {:git/tag "v0.4.0" :git/sha "48726c2"}}
:main-opts ["-m" "stratify.main"]
Then run:
clojure -M:stratify path/to/src -o graph.dgml
Troubleshooting
Stratify needs Clojure 1.12.
In case you get an error Could not locate clojure/repl/deps__init.class:
- Make sure to update Clojure CLI tools to latest version (
clojure --versionshould printClojure CLI version 1.12.0.1479or later). - Alternatively add
org.clojure/clojure {:mvn/version "1.12.0"}to:depsmap explicitly.
Full error message:
Execution error (FileNotFoundException) at stratify.main/eval138$loading (main.clj:1).
Could not locate clojure/repl/deps__init.class, clojure/repl/deps.clj or clojure/repl/deps.cljc on classpath.
~/.clojure/deps.edn :aliases section with added Clojure 1.12:
{:aliases
{:stratify
{:extra-deps {io.github.dundalek/stratify {:git/tag "v0.4.0" :git/sha "48726c2"}
org.clojure/clojure {:mvn/version "1.12.0"}}
:main-opts ["-m" "stratify.main"]
</details>
Options
Usage: stratify <options> <src-paths>
Options:
--metrics-delta Calculate and serve metrics delta report
--include-dependencies Include links to library dependencies
--insert-namespace-node <label> Group vars mixed among namespaces under a node with a given label
--flat-namespaces Render flat namespaces instead of a nested hierarchy
--coverage-file <file> Include line coverage metric from given Codecov file
-o, --out <file> - Output file, default "-" standard output
-f, --from <format> clj Source format, choices:
Language extractors: "clj", "go-lsp", "go-scip", "lua-lsp", "python-scip", "ruby-scip", "rust-lsp", "ts-lsp", "ts-scip", "zig-lsp"
Other formats: "dgml", "dot", "overarch", "pulumi", "scip"
-h, --help Print this help message and exit
--metrics Calculate and serve namespace metrics report
-t, --to <format> dgml Target format, choices: "codecharta", "dep-tree", "dgml"
Source Code extraction
| Language | Namespace Dependencies | Function Dependencies | Test Coverage | |----------|----------|------------|----------| | C / C++ | ✓ | joern, lsp (clangd) | | | Clojure | ✓ | clj-kondo | codecov (cloverage) | | Go | scip | joern, lsp (gopls) | | | Java | ✓ | joern | | | JavaScript / TypeScript | scip | joern, lsp (typescript-language-server) | | | Lua | treesitter | lsp (lua-language-server) | | | Python | scip | joern | | | Ruby | scip | - | | | Rust | ✓ | lsp (rust-analyzer) | | | Zig | ✓ | lsp (zls) | |
Granularity of extractions:
- Namespace dependencies - Coarser-grained dependencies only between modules/files
- (✓) means namespace dependencies are provided by function dependencies implementation
- Function dependencies - Finer-grained including dependencies between functions/methods within modules/files
LSP-based extractors
LSP language servers are used to analyze code. The corresponding language server must be installed and available on the PATH.
For example to extract TypeScript dependencies using typescript-language-server (installed with npm install -g typescript-language-server):
clojure -M:stratify -f ts-lsp -o graph.dgml src
SCIP-based extractors
This approach leverages SCIP index files.
For selected languages SCIP indexers can be invoked automatically.
For example to extract Python dependencies (scip-python must be installed and available on PATH):
clojure -M:stratify -f python-scip -o graph.dgml src
For additional languages generate the index first, the use -f scip to extract the index file:
scip-python index # creates index.scip
clojure -M:stratify -f scip -o graph.dgml index.scip
Joern-based extractors
Joern is a tool for code analysis which includes parsers for multiple languages. It is based on Code Property Graphs (CPG) model which can be used to extract function-level dependencies.
For example to extract Java dependencies:
clojure -M:stratify -f java-joern -o graph.dgml src
Using Visual Studio DGML Editor
Once you extracted the graph use Visual Studio to visualize it.
A downside is that Visual Studio is Windows-only, but it can be run in a Virtual Machine (VM) and there are VM images provided for developers. It is sufficient to use the free Community edition.
- Run Visual Studio in VM (optional)
- VM images for developers in various formats, e.g. for VirtualBox
- Visual Studio 2022 Community edition is pre-installed
- Enable DGML Editor
- menu Tools -> Get Tools and Features (opens Visual Studio Installer) -> Individual Components
- check DGML Editor
- menu Tools -> Get Tools and Features (opens Visual Studio Installer) -> Individual Components
- Install DgmlPowerTools 2022 extension (source, optional)
- provides extra features like neighborhood and butterfly exploration modes
- menu Extensions -> Manage Extensions
3D Code City
- Install dependencies
Install [C
